Browse Source

Don't inherit file descriptor to child process

For non-Mingw32 build, set FD_CLOEXEC to file descriptors which live
beyond function scope.  For Mingw32 build, just pass false to
bInheritHandles parameter of CreateProcessW.
Tatsuhiro Tsujikawa 10 năm trước cách đây
mục cha
commit
5e48e01bf9
4 tập tin đã thay đổi với 29 bổ sung2 xóa
  1. 1 0
      src/AbstractDiskWriter.cc
  2. 3 0
      src/SocketCore.cc
  3. 20 2
      src/util.cc
  4. 5 0
      src/util.h

+ 1 - 0
src/AbstractDiskWriter.cc

@@ -221,6 +221,7 @@ int openFileWithFlags(const std::string& filename, int flags,
                                    util::safeStrerror(errNum).c_str()),
                        errCode);
   }
+  util::make_fd_cloexec(fd);
 #if defined(__APPLE__) && defined(__MACH__)
   // This may reduce memory consumption on Mac OS X.
   fcntl(fd, F_NOCACHE, 1);

+ 3 - 0
src/SocketCore.cc

@@ -202,6 +202,7 @@ void SocketCore::create(int family, int protocol)
     throw DL_ABORT_EX(
         fmt("Failed to create socket. Cause:%s", errorMsg(errNum).c_str()));
   }
+  util::make_fd_cloexec(fd);
   int sockopt = 1;
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t)&sockopt,
                  sizeof(sockopt)) < 0) {
@@ -227,6 +228,7 @@ static sock_t bindInternal(int family, int socktype, int protocol,
     error = errorMsg(errNum);
     return -1;
   }
+  util::make_fd_cloexec(fd);
   int sockopt = 1;
   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t)&sockopt,
                  sizeof(sockopt)) < 0) {
@@ -445,6 +447,7 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port,
       error = errorMsg(errNum);
       continue;
     }
+    util::make_fd_cloexec(fd);
     int sockopt = 1;
     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t)&sockopt,
                    sizeof(sockopt)) < 0) {

+ 20 - 2
src/util.cc

@@ -1900,7 +1900,7 @@ void executeHook(const std::string& command, a2_gid_t gid, size_t numFiles,
   assert(cmdlineLen > 0);
   A2_LOG_INFO(fmt("Executing user command: %s", cmdline.c_str()));
   DWORD rc = CreateProcessW(batch ? utf8ToWChar(cmdexe).c_str() : nullptr,
-                            wcharCmdline.get(), nullptr, nullptr, true, 0,
+                            wcharCmdline.get(), nullptr, nullptr, false, 0,
                             nullptr, 0, &si, &pi);
 
   if (!rc) {
@@ -2087,7 +2087,6 @@ TLSVersion toTLSVersion(const std::string& ver)
 }
 #endif // ENABLE_SSL
 
-
 #ifdef __MINGW32__
 std::string formatLastError(int errNum)
 {
@@ -2105,6 +2104,25 @@ std::string formatLastError(int errNum)
 }
 #endif // __MINGW32__
 
+void make_fd_cloexec(int fd)
+{
+#ifndef __MINGW32__
+  int flags;
+
+  // TODO from linux man page, fcntl() with F_GETFD or F_SETFD does
+  // not return -1 with errno == EINTR.  Historically, aria2 code base
+  // checks this case.  Probably, it is not needed.
+  while ((flags = fcntl(fd, F_GETFD)) == -1 && errno == EINTR)
+    ;
+  if (flags == -1) {
+    return;
+  }
+
+  while (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1 && errno == EINTR)
+    ;
+#endif // !__MINGW32__
+}
+
 } // namespace util
 
 } // namespace aria2

+ 5 - 0
src/util.h

@@ -862,6 +862,11 @@ TLSVersion toTLSVersion(const std::string& ver);
 std::string formatLastError(int errNum);
 #endif // __MINGW32__
 
+// Sets file descriptor file FD_CLOEXEC to |fd|.  This function is
+// noop for Mingw32 build, since we disable inheritance in
+// CreateProcess call.
+void make_fd_cloexec(int fd);
+
 } // namespace util
 
 } // namespace aria2