OSDN Git Service

Add a file open flag that disables O_CLOEXEC.
authorZachary Turner <zturner@google.com>
Fri, 8 Jun 2018 15:15:56 +0000 (15:15 +0000)
committerZachary Turner <zturner@google.com>
Fri, 8 Jun 2018 15:15:56 +0000 (15:15 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334293 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Support/FileSystem.h
lib/Support/Unix/Path.inc
lib/Support/Windows/Path.inc

index 11622aa..0428f83 100644 (file)
@@ -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.
index c4c4cfc..f3f529e 100644 (file)
@@ -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();
 }
index 6017fce..9173206 100644 (file)
@@ -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<wchar_t, 128> 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<file_t> 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;