From 58a53155d02782735d50080cc4efea85be2517c3 Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Fri, 8 Jun 2018 15:15:56 +0000 Subject: [PATCH] Add a file open flag that disables O_CLOEXEC. O_CLOEXEC is the right default, but occasionally you don't want this. This is especially true for tools like debuggers where you might need to spawn the child process with specific files already open, but it's occasionally useful in other scenarios as well, like when you want to do some IPC between parent and child. llvm-svn: 334293 --- include/llvm/Support/FileSystem.h | 6 +++++- lib/Support/Unix/Path.inc | 11 +++++++---- lib/Support/Windows/Path.inc | 20 +++++++++++++++----- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 11622aa52f8..0428f837d2a 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -717,7 +717,11 @@ enum OpenFlags : unsigned { F_Append = 2, // For compatibility /// Delete the file on close. Only makes a difference on windows. - OF_Delete = 4 + OF_Delete = 4, + + /// When a child process is launched, this file should remain open in the + /// child process. + OF_ChildInherit = 8, }; /// Create a uniquely named file. diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index c4c4cfc3afe..f3f529e54d7 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -753,7 +753,8 @@ static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags, Result |= O_APPEND; #ifdef O_CLOEXEC - Result |= O_CLOEXEC; + if (!(Flags & OF_ChildInherit)) + Result |= O_CLOEXEC; #endif return Result; @@ -770,9 +771,11 @@ std::error_code openFile(const Twine &Name, int &ResultFD, 0) return std::error_code(errno, std::generic_category()); #ifndef O_CLOEXEC - int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC); - (void)r; - assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed"); + if (!(Flags & OF_ChildInherit)) { + int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC); + (void)r; + assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed"); + } #endif return std::error_code(); } diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc index 6017fcedc33..9173206d816 100644 --- a/lib/Support/Windows/Path.inc +++ b/lib/Support/Windows/Path.inc @@ -1104,15 +1104,21 @@ static DWORD nativeAccess(FileAccess Access, OpenFlags Flags) { static std::error_code openNativeFileInternal(const Twine &Name, file_t &ResultFile, DWORD Disp, - DWORD Access, DWORD Flags) { + DWORD Access, DWORD Flags, + bool Inherit = false) { SmallVector PathUTF16; if (std::error_code EC = widenPath(Name, PathUTF16)) return EC; + SECURITY_ATTRIBUTES SA; + SA.nLength = sizeof(SA); + SA.lpSecurityDescriptor = nullptr; + SA.bInheritHandle = Inherit; + HANDLE H = ::CreateFileW(PathUTF16.begin(), Access, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, Disp, Flags, NULL); + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, &SA, + Disp, Flags, NULL); if (H == INVALID_HANDLE_VALUE) { DWORD LastError = ::GetLastError(); std::error_code EC = mapWindowsError(LastError); @@ -1140,9 +1146,13 @@ Expected openNativeFile(const Twine &Name, CreationDisposition Disp, DWORD NativeDisp = nativeDisposition(Disp, Flags); DWORD NativeAccess = nativeAccess(Access, Flags); + bool Inherit = false; + if (Flags & OF_ChildInherit) + Inherit = true; + file_t Result; - std::error_code EC = openNativeFileInternal(Name, Result, NativeDisp, - NativeAccess, NativeFlags); + std::error_code EC = openNativeFileInternal( + Name, Result, NativeDisp, NativeAccess, NativeFlags, Inherit); if (EC) return errorCodeToError(EC); return Result;