Bug 827749 - Aggressively duplicate file descriptors. r=cjones.

This commit is contained in:
Ben Turner 2013-01-10 13:00:17 +01:00
parent 7f172bf755
commit 9c8ad1d617
2 changed files with 89 additions and 30 deletions

View File

@ -8,50 +8,93 @@
#include "nsDebug.h"
#ifdef XP_WIN
#include <windows.h>
#define INVALID_HANDLE INVALID_HANDLE_VALUE
#else
#else // XP_WIN
#include <unistd.h>
#define INVALID_HANDLE -1
#ifndef OS_POSIX
#define OS_POSIX
#endif
#include "base/eintr_wrapper.h"
#define INVALID_HANDLE -1
#endif // XP_WIN
using mozilla::ipc::FileDescriptor;
FileDescriptor::FileDescriptor()
: mHandle(INVALID_HANDLE)
: mHandle(INVALID_HANDLE), mMustCloseHandle(false)
{ }
FileDescriptor::FileDescriptor(PlatformHandleType aHandle)
: mHandle(INVALID_HANDLE), mMustCloseHandle(false)
{
DuplicateInCurrentProcess(aHandle);
}
FileDescriptor::~FileDescriptor()
{
if (mMustCloseHandle) {
MOZ_ASSERT(mHandle != INVALID_HANDLE);
#ifdef XP_WIN
if (!CloseHandle(mHandle)) {
NS_WARNING("Failed to close file handle!");
}
#else // XP_WIN
HANDLE_EINTR(close(mHandle));
#endif
}
}
void
FileDescriptor::DuplicateInCurrentProcess(PlatformHandleType aHandle)
{
if (aHandle != INVALID_HANDLE) {
PlatformHandleType newHandle;
#ifdef XP_WIN
if (DuplicateHandle(GetCurrentProcess(), aHandle, GetCurrentProcess(),
&newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
#else // XP_WIN
if ((newHandle = dup(aHandle)) != INVALID_HANDLE) {
#endif
mHandle = newHandle;
mMustCloseHandle = true;
return;
}
NS_WARNING("Failed to duplicate file descriptor!");
}
mHandle = INVALID_HANDLE;
mMustCloseHandle = false;
}
FileDescriptor::PickleType
FileDescriptor::ShareTo(const FileDescriptor::IPDLPrivate&,
FileDescriptor::ProcessHandle aOtherProcess) const
{
#ifdef XP_WIN
if (mHandle == INVALID_HANDLE) {
return INVALID_HANDLE;
}
PlatformHandleType newHandle;
if (!DuplicateHandle(GetCurrentProcess(), mHandle, aOtherProcess, &newHandle,
0, FALSE, DUPLICATE_SAME_ACCESS)) {
#ifdef XP_WIN
if (mHandle != INVALID_HANDLE) {
if (DuplicateHandle(GetCurrentProcess(), mHandle, aOtherProcess,
&newHandle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
// mHandle must still be closed here (since it is an in-process handle
// that we duplicated) so leave mMustCloseHandle unchanged.
return newHandle;
}
NS_WARNING("Failed to duplicate file handle!");
return INVALID_HANDLE;
}
return newHandle;
return INVALID_HANDLE;
#else // XP_WIN
if (mHandle == INVALID_HANDLE) {
return base::FileDescriptor();
if (mHandle != INVALID_HANDLE) {
newHandle = dup(mHandle);
return base::FileDescriptor(newHandle, /* auto_close */ true);
}
PlatformHandleType newHandle = dup(mHandle);
if (newHandle < 0) {
NS_WARNING("Failed to duplicate file descriptor!");
return base::FileDescriptor();
}
// This file descriptor must be closed once the caller is done using it, so
// pass true here for the 'auto_close' argument.
return base::FileDescriptor(newHandle, true);
return base::FileDescriptor();
#endif
MOZ_NOT_REACHED("Must not get here!");

View File

@ -50,18 +50,30 @@ public:
FileDescriptor();
FileDescriptor(PlatformHandleType aHandle)
: mHandle(aHandle)
{ }
FileDescriptor(const FileDescriptor& aOther)
{
*this = aOther;
}
FileDescriptor(PlatformHandleType aHandle);
FileDescriptor(const IPDLPrivate&, const PickleType& aPickle)
#ifdef XP_WIN
: mHandle(aPickle)
: mHandle(aPickle), mMustCloseHandle(false)
#else
: mHandle(aPickle.fd)
: mHandle(aPickle.fd), mMustCloseHandle(false)
#endif
{ }
~FileDescriptor();
FileDescriptor&
operator=(const FileDescriptor& aOther)
{
DuplicateInCurrentProcess(aOther.mHandle);
return *this;
}
// Performs platform-specific actions to duplicate mHandle in the other
// process (e.g. dup() on POSIX, DuplicateHandle() on Windows). Returns a
// pickled value that can be passed to the other process via IPC.
@ -86,7 +98,11 @@ public:
}
private:
void
DuplicateInCurrentProcess(PlatformHandleType aHandle);
PlatformHandleType mHandle;
bool mMustCloseHandle;
};
} // namespace ipc