Fix typo in 9b54bd30006c008b4a951331b273613d5bac3abf
[pm.git] / ipc / glue / FileDescriptorUtils.cpp
blob409ca73230e33e76d9919a024c2f041b8ace38e4
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "FileDescriptorUtils.h"
7 #include "nsIEventTarget.h"
9 #include "nsCOMPtr.h"
10 #include "nsDebug.h"
11 #include "nsNetCID.h"
12 #include "nsServiceManagerUtils.h"
13 #include "nsThreadUtils.h"
14 #include "prio.h"
15 #include "private/pprio.h"
17 #include <errno.h>
18 #ifdef XP_WIN
19 #include <io.h>
20 #else
21 #include <unistd.h>
22 #endif
24 using mozilla::ipc::CloseFileRunnable;
26 #ifdef DEBUG
28 CloseFileRunnable::CloseFileRunnable(const FileDescriptor& aFileDescriptor)
29 : mFileDescriptor(aFileDescriptor)
31 MOZ_ASSERT(aFileDescriptor.IsValid());
34 #endif // DEBUG
36 CloseFileRunnable::~CloseFileRunnable()
38 if (mFileDescriptor.IsValid()) {
39 // It's probably safer to take the main thread IO hit here rather than leak
40 // the file descriptor.
41 CloseFile();
45 NS_IMPL_ISUPPORTS(CloseFileRunnable, nsIRunnable)
47 void
48 CloseFileRunnable::Dispatch()
50 nsCOMPtr<nsIEventTarget> eventTarget =
51 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
52 NS_ENSURE_TRUE_VOID(eventTarget);
54 nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
55 NS_ENSURE_SUCCESS_VOID(rv);
58 void
59 CloseFileRunnable::CloseFile()
61 // It's possible for this to happen on the main thread if the dispatch to the
62 // stream service fails so we can't assert the thread on which we're running.
64 MOZ_ASSERT(mFileDescriptor.IsValid());
66 PRFileDesc* fd =
67 PR_ImportFile(PROsfd(mFileDescriptor.PlatformHandle()));
68 NS_WARN_IF_FALSE(fd, "Failed to import file handle!");
70 mFileDescriptor = FileDescriptor();
72 if (fd) {
73 PR_Close(fd);
74 fd = nullptr;
78 NS_IMETHODIMP
79 CloseFileRunnable::Run()
81 MOZ_ASSERT(!NS_IsMainThread());
83 CloseFile();
84 return NS_OK;
87 namespace mozilla {
88 namespace ipc {
90 FILE*
91 FileDescriptorToFILE(const FileDescriptor& aDesc,
92 const char* aOpenMode)
94 // Debug builds check whether the handle was "used", even if it's
95 // invalid, so that needs to happen first.
96 FileDescriptor::PlatformHandleType handle = aDesc.PlatformHandle();
97 if (!aDesc.IsValid()) {
98 errno = EBADF;
99 return nullptr;
101 #ifdef XP_WIN
102 int fd = _open_osfhandle(reinterpret_cast<intptr_t>(handle), 0);
103 if (fd == -1) {
104 CloseHandle(handle);
105 return nullptr;
107 #else
108 int fd = handle;
109 #endif
110 FILE* file = fdopen(fd, aOpenMode);
111 if (!file) {
112 int saved_errno = errno;
113 close(fd);
114 errno = saved_errno;
116 return file;
119 FileDescriptor
120 FILEToFileDescriptor(FILE* aStream)
122 if (!aStream) {
123 errno = EBADF;
124 return FileDescriptor();
126 #ifdef XP_WIN
127 int fd = _fileno(aStream);
128 if (fd == -1) {
129 return FileDescriptor();
131 return FileDescriptor(reinterpret_cast<HANDLE>(_get_osfhandle(fd)));
132 #else
133 return FileDescriptor(fileno(aStream));
134 #endif
137 } // namespace ipc
138 } // namespace mozilla