Refactor the FD_CLOEXEC/O_NONBLOCK code.

This commit is contained in:
Gunnar Beutner 2013-02-13 13:03:21 +01:00
parent fac2304ae5
commit 26e2da7a7d
5 changed files with 62 additions and 61 deletions

View File

@ -456,23 +456,7 @@ void Application::UpdatePidFile(const String& filename)
BOOST_THROW_EXCEPTION(runtime_error("Could not open PID file '" + filename + "'")); BOOST_THROW_EXCEPTION(runtime_error("Could not open PID file '" + filename + "'"));
#ifndef _WIN32 #ifndef _WIN32
int flags; Utility::SetCloExec(fileno(m_PidFile));
flags = fcntl(fileno(m_PidFile), F_GETFD, 0);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(fileno(m_PidFile), F_SETFD, flags | FD_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (flock(fileno(m_PidFile), LOCK_EX | LOCK_NB) < 0) {
ClosePidFile();
Logger::Write(LogCritical, "base",
"Another instance of the application is "
"already running. Remove the '" + filename + "' file if "
"you're certain that this is not the case.");
Terminate(EXIT_FAILURE);
}
#endif /* _WIN32 */ #endif /* _WIN32 */
fprintf(m_PidFile, "%d", Utility::GetPid()); fprintf(m_PidFile, "%d", Utility::GetPid());

View File

@ -30,34 +30,30 @@ void Process::CreateWorkers(void)
{ {
int fds[2]; int fds[2];
#ifdef HAVE_PIPE2
if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("pipe2() failed.", errno));
#else /* HAVE_PIPE2 */
if (pipe(fds) < 0) if (pipe(fds) < 0)
BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno)); BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
/* Don't bother setting fds[1] to non-blocking/clo-exec as we'll only
* use it in the following dup() call. */
Utility::SetNonBlocking(fds[1]);
Utility::SetCloExec(fds[1]);
#endif /* HAVE_PIPE2 */
m_TaskFd = fds[1]; m_TaskFd = fds[1];
int flags;
flags = fcntl(fds[1], F_GETFD, 0);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(fds[1], F_SETFD, flags | O_NONBLOCK | FD_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
for (int i = 0; i < thread::hardware_concurrency(); i++) { for (int i = 0; i < thread::hardware_concurrency(); i++) {
int childTaskFd; int childTaskFd = dup(fds[0]);
childTaskFd = dup(fds[0]);
if (childTaskFd < 0) if (childTaskFd < 0)
BOOST_THROW_EXCEPTION(PosixException("dup() failed.", errno)); BOOST_THROW_EXCEPTION(PosixException("dup() failed.", errno));
int flags; Utility::SetNonBlocking(childTaskFd);
flags = fcntl(childTaskFd, F_GETFD, 0); Utility::SetCloExec(childTaskFd);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(childTaskFd, F_SETFD, flags | O_NONBLOCK | FD_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
thread t(&Process::WorkerThreadProc, childTaskFd); thread t(&Process::WorkerThreadProc, childTaskFd);
t.detach(); t.detach();
@ -179,26 +175,16 @@ void Process::InitTask(void)
#ifdef HAVE_PIPE2 #ifdef HAVE_PIPE2
if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0) if (pipe2(fds, O_NONBLOCK | O_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("pipe2() failed.", errno));
#else /* HAVE_PIPE2 */ #else /* HAVE_PIPE2 */
if (pipe(fds) < 0) if (pipe(fds) < 0)
#endif /* HAVE_PIPE2 */
BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno)); BOOST_THROW_EXCEPTION(PosixException("pipe() failed.", errno));
#ifndef HAVE_PIPE2 Utility::SetNonBlocking(fds[0]);
int flags; Utility::SetCloExec(fds[0]);
flags = fcntl(fds[0], F_GETFD, 0);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(fds[0], F_SETFD, flags | O_NONBLOCK | FD_CLOEXEC) < 0) Utility::SetNonBlocking(fds[1]);
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno)); Utility::SetCloExec(fds[1]);
flags = fcntl(fds[1], F_GETFD, 0);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(fds[1], F_SETFD, flags | O_NONBLOCK | FD_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
#endif /* HAVE_PIPE2 */ #endif /* HAVE_PIPE2 */
// build argv // build argv

View File

@ -70,17 +70,9 @@ void Socket::SetFD(SOCKET fd)
{ {
/* mark the socket as non-blocking and close-on-exec */ /* mark the socket as non-blocking and close-on-exec */
if (fd != INVALID_SOCKET) { if (fd != INVALID_SOCKET) {
Utility::SetNonBlockingSocket(fd);
#ifndef _WIN32 #ifndef _WIN32
int flags; Utility::SetCloExec(fd);
flags = fcntl(fd, F_GETFD, 0);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(fd, F_SETFD, flags | O_NONBLOCK | FD_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
#else /* _WIN32 */
unsigned long lTrue = 1;
ioctlsocket(fd, FIONBIO, &lTrue);
#endif /* _WIN32 */ #endif /* _WIN32 */
} }
@ -219,7 +211,7 @@ String Socket::GetPeerAddress(void)
* @param message The error message. * @param message The error message.
* @param errorCode The error code. * @param errorCode The error code.
*/ */
SocketException::SocketException(const String& message, int errorCode) SocketException::SocketException(const String& message, int errorCode)
{ {
#ifdef _WIN32 #ifdef _WIN32
String details = Win32Exception::FormatErrorCode(errorCode); String details = Win32Exception::FormatErrorCode(errorCode);

View File

@ -526,3 +526,35 @@ void Utility::WaitUntil(const function<bool (void)>& predicate)
Application::ProcessEvents(); Application::ProcessEvents();
} }
void Utility::SetNonBlocking(int fd)
{
int flags;
flags = fcntl(fd, F_GETFL, 0);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
}
void Utility::SetCloExec(int fd)
{
int flags;
flags = fcntl(fd, F_GETFD, 0);
if (flags < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
BOOST_THROW_EXCEPTION(PosixException("fcntl failed", errno));
}
void Utility::SetNonBlockingSocket(SOCKET s)
{
#ifndef _WIN32
SetNonBlocking(s);
#else /* _WIN32 */
unsigned long lTrue = 1;
ioctlsocket(s, FIONBIO, &lTrue);
#endif /* _WIN32 */
}

View File

@ -68,6 +68,13 @@ public:
#endif /* _WIN32 */ #endif /* _WIN32 */
LoadIcingaLibrary(const String& library, bool module); LoadIcingaLibrary(const String& library, bool module);
#ifndef _WIN32
static void SetNonBlocking(int fd);
static void SetCloExec(int fd);
#endif /* _WIN32 */
static void SetNonBlockingSocket(SOCKET s);
private: private:
static bool m_SSLInitialized; static bool m_SSLInitialized;