Explorar el Código

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 hace 10 años
padre
commit
5e48e01bf9
Se han modificado 4 ficheros con 29 adiciones y 2 borrados
  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