فهرست منبع

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 سال پیش
والد
کامیت
5e48e01bf9
4فایلهای تغییر یافته به همراه29 افزوده شده و 2 حذف شده
  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