/* Success */
-if (rc >= 0) return 0;
+if (rc >= 0)
+ {
+ callout_address = string_sprintf("[%s]:%d", address, port);
+ return 0;
+ }
/* A failure whose error code is "Interrupted system call" is in fact
an externally applied timeout if the signal handler has been run. */
path, strerror(err));
return -1;
}
+callout_address = string_copy(path);
return sock;
}
fd_ready(int fd, int timeout)
{
fd_set select_inset;
-struct timeval tv;
time_t start_recv = time(NULL);
+int time_left = timeout;
int rc;
-if (timeout <= 0)
+if (time_left <= 0)
{
errno = ETIMEDOUT;
return FALSE;
do
{
+ struct timeval tv = { time_left, 0 };
FD_ZERO (&select_inset);
FD_SET (fd, &select_inset);
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
/*DEBUG(D_transport) debug_printf("waiting for data on fd\n");*/
rc = select(fd + 1, (SELECT_ARG2_TYPE *)&select_inset, NULL, NULL, &tv);
Aug 2004: Somebody set up a cron job that ran exiwhat every 2 minutes, making
the interrupt not at all rare. Since the timeout is typically more than 2
minutes, the effect was to block the timeout completely. To prevent this
- happening again, we do an explicit time test. */
+ happening again, we do an explicit time test and adjust the timeout
+ accordingly */
if (rc < 0 && errno == EINTR)
{
DEBUG(D_transport) debug_printf("EINTR while waiting for socket data\n");
- if (time(NULL) - start_recv < timeout) continue;
- DEBUG(D_transport) debug_printf("total wait time exceeds timeout\n");
- }
- /* Handle a timeout, and treat any other select error as a timeout, including
- an EINTR when we have been in this loop for longer than timeout. */
+ /* Watch out, 'continue' jumps to the condition, not to the loops top */
+ time_left = timeout - (time(NULL) - start_recv);
+ if (time_left > 0) continue;
+ }
if (rc <= 0)
{
return FALSE;
}
- /* If the socket is ready, break out of the loop. */
+ /* Checking the FD_ISSET is not enough, if we're interrupted, the
+ select_inset may still contain the 'input'. */
}
while (rc < 0 || !FD_ISSET(fd, &select_inset));
return TRUE;