summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-02-08 00:09:17 +0900
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2016-02-08 00:09:17 +0900
commit5e48e01bf9941d1d257ee9b5c79142b2d43d9af1 (patch)
tree2feaa2ac6b3763b533b1a41532cbf0e5b6d8c120
parentab40ee58b878f8d11b2985c705bef24a2914760a (diff)
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.
-rw-r--r--src/AbstractDiskWriter.cc1
-rw-r--r--src/SocketCore.cc3
-rw-r--r--src/util.cc22
-rw-r--r--src/util.h5
4 files changed, 29 insertions, 2 deletions
diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc
index 2420b6a8..4d62bf97 100644
--- a/src/AbstractDiskWriter.cc
+++ b/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);
diff --git a/src/SocketCore.cc b/src/SocketCore.cc
index 3f04ee54..e73f5dcd 100644
--- a/src/SocketCore.cc
+++ b/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) {
diff --git a/src/util.cc b/src/util.cc
index 7cfbf237..1d9d8bbf 100644
--- a/src/util.cc
+++ b/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
diff --git a/src/util.h b/src/util.h
index fe802af4..14b5d146 100644
--- a/src/util.h
+++ b/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