diff options
author | Jeremy Allison <jra@samba.org> | 2005-01-06 00:45:39 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:53:47 -0500 |
commit | 1afc2e01ce7803a7b54715acfbcb824130f673df (patch) | |
tree | 1d42c3f26458b80078e7b7e611edba8ba27ece79 | |
parent | d097ea490525e7a35739dae6a295fd03ba52cfc0 (diff) | |
download | samba-1afc2e01ce7803a7b54715acfbcb824130f673df.tar.gz samba-1afc2e01ce7803a7b54715acfbcb824130f673df.tar.bz2 samba-1afc2e01ce7803a7b54715acfbcb824130f673df.zip |
r4545: Fix based on work by Derrell.Lipman@UnwiredUniverse.com :
* In an application with signals, it was possible for functions to block
indefinitely while awaiting timeouts. This patch ensures that if a system
call with a timeout is aborted and needs to be restarted, it is restarted
with a timeout which is adjusted for the amount of time already waited.
Jeremy.
(This used to be commit 3a0d426764ab8bac561a47329500a03a52a00fa3)
-rw-r--r-- | source3/lib/select.c | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/source3/lib/select.c b/source3/lib/select.c index f88ad52de6..f3d119bdb1 100644 --- a/source3/lib/select.c +++ b/source3/lib/select.c @@ -128,12 +128,23 @@ int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorf { int ret; fd_set *readfds2, readfds_buf, *writefds2, writefds_buf, *errorfds2, errorfds_buf; - struct timeval tval2, *ptval; + struct timeval tval2, *ptval, end_time; readfds2 = (readfds ? &readfds_buf : NULL); writefds2 = (writefds ? &writefds_buf : NULL); errorfds2 = (errorfds ? &errorfds_buf : NULL); - ptval = (tval ? &tval2 : NULL); + if (tval) { + GetTimeOfDay(&end_time); + end_time.tv_sec += tval->tv_sec; + end_time.tv_usec += tval->tv_usec; + end_time.tv_sec += end_time.tv_usec / 1000000; + end_time.tv_usec %= 1000000; + errno = 0; + tval2 = *tval; + ptval = &tval2; + } else { + ptval = NULL; + } do { if (readfds) @@ -142,8 +153,19 @@ int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorf writefds_buf = *writefds; if (errorfds) errorfds_buf = *errorfds; - if (tval) - tval2 = *tval; + if (ptval && (errno == EINTR)) { + struct timeval now_time; + SMB_BIG_INT tdif; + + GetTimeOfDay(&now_time); + tdif = usec_time_diff(&end_time, &now_time); + if (tdif <= 0) { + ret = 0; /* time expired. */ + break; + } + ptval->tv_sec = tdif / 1000000; + ptval->tv_usec = tdif % 1000000; + } ret = sys_select(maxfd, readfds2, writefds2, errorfds2, ptval); } while (ret == -1 && errno == EINTR); |