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 "nsThreadUtils.h" 16 #include "prio.h" 17 #include "private/pprio.h" 18 19 #include <errno.h> 20 #ifdef XP_WIN 21 #include <io.h> 22 #else 23 #include <unistd.h> 24 #endif 25 26 using mozilla::ipc::CloseFileRunnable; 27 28 #ifdef DEBUG 29 CloseFileRunnable(const FileDescriptor & aFileDescriptor)30CloseFileRunnable::CloseFileRunnable(const FileDescriptor& aFileDescriptor) 31 : mFileDescriptor(aFileDescriptor) { 32 MOZ_ASSERT(aFileDescriptor.IsValid()); 33 } 34 35 #endif // DEBUG 36 ~CloseFileRunnable()37CloseFileRunnable::~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(); 42 } 43 } 44 NS_IMPL_ISUPPORTS(CloseFileRunnable,nsIRunnable)45NS_IMPL_ISUPPORTS(CloseFileRunnable, nsIRunnable) 46 47 void CloseFileRunnable::Dispatch() { 48 nsCOMPtr<nsIEventTarget> eventTarget = 49 do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID); 50 NS_ENSURE_TRUE_VOID(eventTarget); 51 52 nsresult rv = eventTarget->Dispatch(this, NS_DISPATCH_NORMAL); 53 NS_ENSURE_SUCCESS_VOID(rv); 54 } 55 CloseFile()56void CloseFileRunnable::CloseFile() { 57 // It's possible for this to happen on the main thread if the dispatch to the 58 // stream service fails so we can't assert the thread on which we're running. 59 mFileDescriptor = FileDescriptor(); 60 } 61 62 NS_IMETHODIMP Run()63CloseFileRunnable::Run() { 64 MOZ_ASSERT(!NS_IsMainThread()); 65 66 CloseFile(); 67 return NS_OK; 68 } 69 70 namespace mozilla { 71 namespace ipc { 72 FileDescriptorToFILE(const FileDescriptor & aDesc,const char * aOpenMode)73FILE* FileDescriptorToFILE(const FileDescriptor& aDesc, const char* aOpenMode) { 74 if (!aDesc.IsValid()) { 75 errno = EBADF; 76 return nullptr; 77 } 78 auto handle = aDesc.ClonePlatformHandle(); 79 #ifdef XP_WIN 80 int fd = _open_osfhandle(static_cast<intptr_t>(handle.get()), 0); 81 if (fd == -1) { 82 return nullptr; 83 } 84 Unused << handle.release(); 85 #else 86 int fd = handle.release(); 87 #endif 88 FILE* file = fdopen(fd, aOpenMode); 89 if (!file) { 90 int saved_errno = errno; 91 close(fd); 92 errno = saved_errno; 93 } 94 return file; 95 } 96 FILEToFileDescriptor(FILE * aStream)97FileDescriptor FILEToFileDescriptor(FILE* aStream) { 98 if (!aStream) { 99 errno = EBADF; 100 return FileDescriptor(); 101 } 102 #ifdef XP_WIN 103 int fd = _fileno(aStream); 104 if (fd == -1) { 105 return FileDescriptor(); 106 } 107 return FileDescriptor(reinterpret_cast<HANDLE>(_get_osfhandle(fd))); 108 #else 109 return FileDescriptor(fileno(aStream)); 110 #endif 111 } 112 113 } // namespace ipc 114 } // namespace mozilla 115