浏览代码

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 9 年之前
父节点
当前提交
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