Rather than failing to compile on platforms which lack POLLRDHUP such as FreeBSD, simply fallback to the old method of sleeping. This leaves the porting suggestions as a comment in case someone wants to implement a better solution for particular platforms. --- server/public.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/server/public.c b/server/public.c index a992df1..630de9b 100644 --- a/server/public.c +++ b/server/public.c @@ -304,6 +304,16 @@ nbdkit_realpath (const char *path) int nbdkit_nanosleep (unsigned sec, unsigned nsec) { + struct timespec ts; + + if (sec >= INT_MAX - nsec / 1000000000) { + nbdkit_error ("sleep request is too long"); + errno = EINVAL; + return -1; + } + ts.tv_sec = sec + nsec / 1000000000; + ts.tv_nsec = nsec % 1000000000; + #if defined HAVE_PPOLL && defined POLLRDHUP /* End the sleep early if any of these happen: * - nbdkit has received a signal to shut down the server @@ -311,7 +321,6 @@ nbdkit_nanosleep (unsigned sec, unsigned nsec) * NBD_CMD_DISC or a problem with the connection * - the input socket detects POLLRDHUP/POLLHUP/POLLERR */ - struct timespec ts; struct connection *conn = threadlocal_get_conn (); struct pollfd fds[] = { [0].fd = quit_fd, @@ -323,14 +332,6 @@ nbdkit_nanosleep (unsigned sec, unsigned nsec) }; sigset_t all; - if (sec >= INT_MAX - nsec / 1000000000) { - nbdkit_error ("sleep request is too long"); - errno = EINVAL; - return -1; - } - ts.tv_sec = sec + nsec / 1000000000; - ts.tv_nsec = nsec % 1000000000; - /* Block all signals to this thread during the poll, so we don't * have to worry about EINTR */ @@ -354,9 +355,13 @@ nbdkit_nanosleep (unsigned sec, unsigned nsec) nbdkit_error ("aborting sleep to shut down"); errno = ESHUTDOWN; return -1; + #else -# error "Please port this to your platform" - /* Porting ideas, in order of preference: + /* The fallback path simply calls ordinary nanosleep, and will + * cause long delays on server shutdown. + * + * If however you want to port this to your platform, then + * porting ideas, in order of preference: * - POSIX requires pselect; it's a bit clunkier to set up than poll, * but the same ability to atomically mask all signals and operate * on struct timespec makes it similar to the preferred ppoll interface @@ -364,8 +369,13 @@ nbdkit_nanosleep (unsigned sec, unsigned nsec) * a recalculation of the timeout to still reach the end time (masking * signals in that case is not safe, as it is a non-atomic race) */ - nbdkit_error ("nbdkit_nanosleep not yet ported to systems without ppoll"); - errno = ENOSYS; - return -1; + int r; + + r = nanosleep (&ts, NULL); + if (r == -1 && errno != EINTR && errno != EAGAIN) { + nbdkit_error ("nanosleep: %m"); + return -1; + } + return 0; #endif } -- 2.22.0