FileDescriptorUtils.cpp (2702B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "FileDescriptorUtils.h" 8 9 #include "nsIEventTarget.h" 10 11 #include "nsCOMPtr.h" 12 #include "nsDebug.h" 13 #include "nsNetCID.h" 14 #include "nsServiceManagerUtils.h" 15 #include "prio.h" 16 #include "private/pprio.h" 17 18 #include <errno.h> 19 #ifdef XP_WIN 20 # include <io.h> 21 #else 22 # include <unistd.h> 23 #endif 24 25 using mozilla::ipc::CloseFileRunnable; 26 27 CloseFileRunnable::CloseFileRunnable(const FileDescriptor& aFileDescriptor) 28 : Runnable("CloseFileRunnable"), mFileDescriptor(aFileDescriptor) { 29 MOZ_ASSERT(aFileDescriptor.IsValid()); 30 } 31 32 CloseFileRunnable::~CloseFileRunnable() { 33 if (mFileDescriptor.IsValid()) { 34 // It's probably safer to take the main thread IO hit here rather than leak 35 // the file descriptor. 36 CloseFile(); 37 } 38 } 39 40 NS_IMPL_ISUPPORTS_INHERITED0(CloseFileRunnable, Runnable) 41 42 void CloseFileRunnable::Dispatch() { 43 nsCOMPtr<nsIEventTarget> eventTarget = 44 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); 45 NS_ENSURE_TRUE_VOID(eventTarget); 46 47 nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL); 48 NS_ENSURE_SUCCESS_VOID(rv); 49 } 50 51 void CloseFileRunnable::CloseFile() { 52 // It's possible for this to happen on the main thread if the dispatch to the 53 // stream service fails so we can't assert the thread on which we're running. 54 mFileDescriptor = FileDescriptor(); 55 } 56 57 NS_IMETHODIMP 58 CloseFileRunnable::Run() { 59 MOZ_ASSERT(!NS_IsMainThread()); 60 61 CloseFile(); 62 return NS_OK; 63 } 64 65 namespace mozilla { 66 namespace ipc { 67 68 FILE* FileDescriptorToFILE(const FileDescriptor& aDesc, const char* aOpenMode) { 69 if (!aDesc.IsValid()) { 70 errno = EBADF; 71 return nullptr; 72 } 73 auto handle = aDesc.ClonePlatformHandle(); 74 #ifdef XP_WIN 75 int fd = _open_osfhandle(static_cast<intptr_t>(handle.get()), 0); 76 if (fd == -1) { 77 return nullptr; 78 } 79 (void)handle.release(); 80 #else 81 int fd = handle.release(); 82 #endif 83 FILE* file = fdopen(fd, aOpenMode); 84 if (!file) { 85 int saved_errno = errno; 86 close(fd); 87 errno = saved_errno; 88 } 89 return file; 90 } 91 92 FileDescriptor FILEToFileDescriptor(FILE* aStream) { 93 if (!aStream) { 94 errno = EBADF; 95 return FileDescriptor(); 96 } 97 #ifdef XP_WIN 98 int fd = _fileno(aStream); 99 if (fd == -1) { 100 return FileDescriptor(); 101 } 102 return FileDescriptor(reinterpret_cast<HANDLE>(_get_osfhandle(fd))); 103 #else 104 return FileDescriptor(fileno(aStream)); 105 #endif 106 } 107 108 } // namespace ipc 109 } // namespace mozilla