summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2005-01-06 00:45:39 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 10:53:47 -0500
commit1afc2e01ce7803a7b54715acfbcb824130f673df (patch)
tree1d42c3f26458b80078e7b7e611edba8ba27ece79
parentd097ea490525e7a35739dae6a295fd03ba52cfc0 (diff)
downloadsamba-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.c30
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);