summaryrefslogtreecommitdiffstats
path: root/ipc/glue/FileDescriptorUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/glue/FileDescriptorUtils.cpp')
-rw-r--r--ipc/glue/FileDescriptorUtils.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/ipc/glue/FileDescriptorUtils.cpp b/ipc/glue/FileDescriptorUtils.cpp
new file mode 100644
index 000000000..e30bc97d8
--- /dev/null
+++ b/ipc/glue/FileDescriptorUtils.cpp
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "FileDescriptorUtils.h"
+
+#include "nsIEventTarget.h"
+
+#include "nsCOMPtr.h"
+#include "nsDebug.h"
+#include "nsNetCID.h"
+#include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
+#include "prio.h"
+#include "private/pprio.h"
+
+#include <errno.h>
+#ifdef XP_WIN
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+using mozilla::ipc::CloseFileRunnable;
+
+#ifdef DEBUG
+
+CloseFileRunnable::CloseFileRunnable(const FileDescriptor& aFileDescriptor)
+: mFileDescriptor(aFileDescriptor)
+{
+ MOZ_ASSERT(aFileDescriptor.IsValid());
+}
+
+#endif // DEBUG
+
+CloseFileRunnable::~CloseFileRunnable()
+{
+ if (mFileDescriptor.IsValid()) {
+ // It's probably safer to take the main thread IO hit here rather than leak
+ // the file descriptor.
+ CloseFile();
+ }
+}
+
+NS_IMPL_ISUPPORTS(CloseFileRunnable, nsIRunnable)
+
+void
+CloseFileRunnable::Dispatch()
+{
+ nsCOMPtr<nsIEventTarget> eventTarget =
+ do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
+ NS_ENSURE_TRUE_VOID(eventTarget);
+
+ nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
+ NS_ENSURE_SUCCESS_VOID(rv);
+}
+
+void
+CloseFileRunnable::CloseFile()
+{
+ // It's possible for this to happen on the main thread if the dispatch to the
+ // stream service fails so we can't assert the thread on which we're running.
+ mFileDescriptor = FileDescriptor();
+}
+
+NS_IMETHODIMP
+CloseFileRunnable::Run()
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ CloseFile();
+ return NS_OK;
+}
+
+namespace mozilla {
+namespace ipc {
+
+FILE*
+FileDescriptorToFILE(const FileDescriptor& aDesc,
+ const char* aOpenMode)
+{
+ if (!aDesc.IsValid()) {
+ errno = EBADF;
+ return nullptr;
+ }
+ auto handle = aDesc.ClonePlatformHandle();
+#ifdef XP_WIN
+ int fd = _open_osfhandle(static_cast<intptr_t>(handle.get()), 0);
+ if (fd == -1) {
+ return nullptr;
+ }
+ Unused << handle.release();
+#else
+ int fd = handle.release();
+#endif
+ FILE* file = fdopen(fd, aOpenMode);
+ if (!file) {
+ int saved_errno = errno;
+ close(fd);
+ errno = saved_errno;
+ }
+ return file;
+}
+
+FileDescriptor
+FILEToFileDescriptor(FILE* aStream)
+{
+ if (!aStream) {
+ errno = EBADF;
+ return FileDescriptor();
+ }
+#ifdef XP_WIN
+ int fd = _fileno(aStream);
+ if (fd == -1) {
+ return FileDescriptor();
+ }
+ return FileDescriptor(reinterpret_cast<HANDLE>(_get_osfhandle(fd)));
+#else
+ return FileDescriptor(fileno(aStream));
+#endif
+}
+
+} // namespace ipc
+} // namespace mozilla