* Support platforms that don't have O_ASYNC (e.g. OpenSolaris

apparently).
This commit is contained in:
Eelco Dolstra 2009-09-30 11:32:04 +00:00
parent 1a8f8fd86f
commit 96f1517831

View file

@ -20,9 +20,18 @@
using namespace nix; using namespace nix;
/* On platforms that have O_ASYNC, we can detect when a client
disconnects and immediately kill any ongoing builds. On platforms
that lack it, we only notice the disconnection the next time we try
to write to the client. So if you have a builder that never
generates output on stdout/stderr, the worker will never notice
that the client has disconnected until the builder terminates. */
#ifdef O_ASYNC
#define HAVE_HUP_NOTIFICATION
#ifndef SIGPOLL #ifndef SIGPOLL
#define SIGPOLL SIGIO #define SIGPOLL SIGIO
#endif #endif
#endif
static FdSource from(STDIN_FILENO); static FdSource from(STDIN_FILENO);
@ -90,7 +99,7 @@ static bool isFarSideClosed(int socket)
/* A SIGPOLL signal is received when data is available on the client /* A SIGPOLL signal is received when data is available on the client
communication scoket, or when the client has closed its side of the communication socket, or when the client has closed its side of the
socket. This handler is enabled at precisely those moments in the socket. This handler is enabled at precisely those moments in the
protocol when we're doing work and the client is supposed to be protocol when we're doing work and the client is supposed to be
quiet. Thus, if we get a SIGPOLL signal, it means that the client quiet. Thus, if we get a SIGPOLL signal, it means that the client
@ -131,12 +140,14 @@ static void sigPollHandler(int sigNo)
static void setSigPollAction(bool enable) static void setSigPollAction(bool enable)
{ {
#ifdef HAVE_HUP_NOTIFICATION
struct sigaction act, oact; struct sigaction act, oact;
act.sa_handler = enable ? sigPollHandler : SIG_IGN; act.sa_handler = enable ? sigPollHandler : SIG_IGN;
sigfillset(&act.sa_mask); sigfillset(&act.sa_mask);
act.sa_flags = 0; act.sa_flags = 0;
if (sigaction(SIGPOLL, &act, &oact)) if (sigaction(SIGPOLL, &act, &oact))
throw SysError("setting handler for SIGPOLL"); throw SysError("setting handler for SIGPOLL");
#endif
} }
@ -520,12 +531,14 @@ static void processConnection()
myPid = getpid(); myPid = getpid();
writeToStderr = tunnelStderr; writeToStderr = tunnelStderr;
#ifdef HAVE_HUP_NOTIFICATION
/* Allow us to receive SIGPOLL for events on the client socket. */ /* Allow us to receive SIGPOLL for events on the client socket. */
setSigPollAction(false); setSigPollAction(false);
if (fcntl(from.fd, F_SETOWN, getpid()) == -1) if (fcntl(from.fd, F_SETOWN, getpid()) == -1)
throw SysError("F_SETOWN"); throw SysError("F_SETOWN");
if (fcntl(from.fd, F_SETFL, fcntl(from.fd, F_GETFL, 0) | FASYNC) == -1) if (fcntl(from.fd, F_SETFL, fcntl(from.fd, F_GETFL, 0) | O_ASYNC) == -1)
throw SysError("F_SETFL"); throw SysError("F_SETFL");
#endif
/* Exchange the greeting. */ /* Exchange the greeting. */
unsigned int magic = readInt(from); unsigned int magic = readInt(from);
@ -663,11 +676,12 @@ static void daemonLoop()
AutoCloseFD remote = accept(fdSocket, AutoCloseFD remote = accept(fdSocket,
(struct sockaddr *) &remoteAddr, &remoteAddrLen); (struct sockaddr *) &remoteAddr, &remoteAddrLen);
checkInterrupt(); checkInterrupt();
if (remote == -1) if (remote == -1) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
else else
throw SysError("accepting connection"); throw SysError("accepting connection");
}
printMsg(lvlInfo, format("accepted connection %1%") % remote); printMsg(lvlInfo, format("accepted connection %1%") % remote);