1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "mojo/edk/embedder/platform_handle.h"
6 
7 #include "build/build_config.h"
8 #if defined(OS_POSIX)
9 #include <unistd.h>
10 #elif defined(OS_WIN)
11 #include <windows.h>
12 #else
13 #error "Platform not yet supported."
14 #endif
15 
16 #include "base/logging.h"
17 
18 namespace mojo {
19 namespace edk {
20 
CloseIfNecessary()21 void PlatformHandle::CloseIfNecessary() {
22   if (!is_valid())
23     return;
24 
25 #if defined(OS_POSIX)
26   if (type == Type::POSIX) {
27     bool success = (close(handle) == 0);
28     DPCHECK(success);
29     handle = -1;
30   }
31 #if defined(OS_MACOSX) && !defined(OS_IOS)
32   else if (type == Type::MACH) {
33     kern_return_t rv = mach_port_deallocate(mach_task_self(), port);
34     DPCHECK(rv == KERN_SUCCESS);
35     port = MACH_PORT_NULL;
36   }
37 #endif  // defined(OS_MACOSX) && !defined(OS_IOS)
38 #elif defined(OS_WIN)
39   if (owning_process != base::GetCurrentProcessHandle()) {
40     // This handle may have been duplicated to a new target process but not yet
41     // sent there. In this case CloseHandle should NOT be called. From MSDN
42     // documentation for DuplicateHandle[1]:
43     //
44     //    Normally the target process closes a duplicated handle when that
45     //    process is finished using the handle. To close a duplicated handle
46     //    from the source process, call DuplicateHandle with the following
47     //    parameters:
48     //
49     //    * Set hSourceProcessHandle to the target process from the
50     //      call that created the handle.
51     //    * Set hSourceHandle to the duplicated handle to close.
52     //    * Set lpTargetHandle to NULL.
53     //    * Set dwOptions to DUPLICATE_CLOSE_SOURCE.
54     //
55     // [1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms724251
56     //
57     // NOTE: It's possible for this operation to fail if the owning process
58     // was terminated or is in the process of being terminated. Either way,
59     // there is nothing we can reasonably do about failure, so we ignore it.
60     DuplicateHandle(owning_process, handle, NULL, &handle, 0, FALSE,
61                     DUPLICATE_CLOSE_SOURCE);
62     return;
63   }
64 
65   bool success = !!CloseHandle(handle);
66   DPCHECK(success);
67   handle = INVALID_HANDLE_VALUE;
68 #else
69 #error "Platform not yet supported."
70 #endif
71 }
72 
73 }  // namespace edk
74 }  // namespace mojo
75