select-0.4: src/System/Posix/IO/Select/cbits.c
#define _POSIX_C_SOURCE 200112L
#include <stdlib.h>
#include <sys/select.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include "cbits.h"
#ifndef NDEBUG
#include <stdio.h>
#endif
int xselect(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, struct timeval* timeout)
{
struct timespec remaining;
int ret;
struct timespec start;
struct timespec current;
struct timespec stop;
if (timeout != NULL)
{
remaining.tv_sec = timeout->tv_sec;
remaining.tv_nsec = timeout->tv_usec*1000;
clock_gettime(CLOCK_MONOTONIC, &start);
stop.tv_sec = start.tv_sec + timeout->tv_sec;
stop.tv_nsec = start.tv_nsec + timeout->tv_usec*1000;
}
fd_set readfds_orig = *readfds;
fd_set writefds_orig = *writefds;
fd_set exceptfds_orig = *exceptfds;
for (;;)
{
#ifndef NDEBUG
if (timeout != NULL)
{
printf("C: Remaining time: %ld s, %ld ns\n", remaining.tv_sec, remaining.tv_nsec);
printf("C: Will select for %ld s, %ld us\n", timeout->tv_sec, timeout->tv_usec);
}
else
printf("C: Will select forever.\n");
#endif
ret = select(nfds, readfds, writefds, exceptfds, timeout);
if (ret == -1 && errno == EINTR)
{
#ifndef NDEBUG
printf("C: Was interrupted.\n");
#endif
if (timeout != NULL) // Case of finite timeouts.
{
clock_gettime(CLOCK_MONOTONIC, ¤t);
remaining.tv_sec = stop.tv_sec - current.tv_sec;
remaining.tv_nsec = stop.tv_nsec - current.tv_nsec;
while (remaining.tv_nsec > 1000000000)
{
remaining.tv_sec++;
remaining.tv_nsec -= 1000000000;
}
while (remaining.tv_nsec < 0)
{
remaining.tv_sec--;
remaining.tv_nsec += 1000000000;
}
if (remaining.tv_sec < 0)
{
remaining.tv_sec = 0;
remaining.tv_nsec = 0;
}
#ifndef NDEBUG
printf("C: Was interrupted with %ld s, %ld ns remaining\n", remaining.tv_sec, remaining.tv_nsec);
#endif
// Set up for retry.
timeout->tv_sec = remaining.tv_sec;
timeout->tv_usec = remaining.tv_nsec/1000;
}
// Set up for retry (also in infinite case).
*readfds = readfds_orig;
*writefds = writefds_orig;
*exceptfds = exceptfds_orig;
#ifndef NDEBUG
printf("C: Retrying select.\n");
#endif
}
else
return ret;
}
return -2; // Cannot happen.
}