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.
pull/565/head
Tatsuhiro Tsujikawa 2016-02-08 00:09:17 +09:00
parent ab40ee58b8
commit 5e48e01bf9
4 changed files with 29 additions and 2 deletions

View File

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

View File

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

View File

@ -1900,7 +1900,7 @@ void executeHook(const std::string& command, a2_gid_t gid, size_t numFiles,
assert(cmdlineLen > 0); assert(cmdlineLen > 0);
A2_LOG_INFO(fmt("Executing user command: %s", cmdline.c_str())); A2_LOG_INFO(fmt("Executing user command: %s", cmdline.c_str()));
DWORD rc = CreateProcessW(batch ? utf8ToWChar(cmdexe).c_str() : nullptr, 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); nullptr, 0, &si, &pi);
if (!rc) { if (!rc) {
@ -2087,7 +2087,6 @@ TLSVersion toTLSVersion(const std::string& ver)
} }
#endif // ENABLE_SSL #endif // ENABLE_SSL
#ifdef __MINGW32__ #ifdef __MINGW32__
std::string formatLastError(int errNum) std::string formatLastError(int errNum)
{ {
@ -2105,6 +2104,25 @@ std::string formatLastError(int errNum)
} }
#endif // __MINGW32__ #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 util
} // namespace aria2 } // namespace aria2

View File

@ -862,6 +862,11 @@ TLSVersion toTLSVersion(const std::string& ver);
std::string formatLastError(int errNum); std::string formatLastError(int errNum);
#endif // __MINGW32__ #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 util
} // namespace aria2 } // namespace aria2