summaryrefslogtreecommitdiffstats
path: root/lib/libc/asr/asr.c
diff options
context:
space:
mode:
authorjmatthew <jmatthew@openbsd.org>2016-05-26 06:59:42 +0000
committerjmatthew <jmatthew@openbsd.org>2016-05-26 06:59:42 +0000
commiteb76e4bcd6b77ed60e3ab89a12f927a3ac460942 (patch)
treeb8c3885670aabbf4db63e08936df18cc6430cb4e /lib/libc/asr/asr.c
parentMake format conversion routines return the number of frames (diff)
downloadwireguard-openbsd-eb76e4bcd6b77ed60e3ab89a12f927a3ac460942.tar.xz
wireguard-openbsd-eb76e4bcd6b77ed60e3ab89a12f927a3ac460942.zip
Calculate elapsed time in poll() and subtract that from the remaining time
when restarting poll() after receiving a signal. The ruby runtime send signals to threads periodically, so without accounting for elapsed time, the timeout would never expire if we didn't get a response from a nameserver. ok deraadt@ eric@
Diffstat (limited to 'lib/libc/asr/asr.c')
-rw-r--r--lib/libc/asr/asr.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/lib/libc/asr/asr.c b/lib/libc/asr/asr.c
index 36fd724e8cb..e39d60dc262 100644
--- a/lib/libc/asr/asr.c
+++ b/lib/libc/asr/asr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: asr.c,v 1.51 2016/02/24 20:52:53 eric Exp $ */
+/* $OpenBSD: asr.c,v 1.52 2016/05/26 06:59:42 jmatthew Exp $ */
/*
* Copyright (c) 2010-2012 Eric Faurot <eric@openbsd.org>
*
@@ -169,15 +169,30 @@ int
asr_run_sync(struct asr_query *as, struct asr_result *ar)
{
struct pollfd fds[1];
- int r, saved_errno = errno;
+ struct timespec pollstart, pollend, elapsed;
+ int timeout, r, p, saved_errno = errno;
while ((r = asr_run(as, ar)) == ASYNC_COND) {
fds[0].fd = ar->ar_fd;
fds[0].events = (ar->ar_cond == ASR_WANT_READ) ? POLLIN:POLLOUT;
+
+ timeout = ar->ar_timeout;
again:
- r = poll(fds, 1, ar->ar_timeout);
- if (r == -1 && errno == EINTR)
+ if (clock_gettime(CLOCK_MONOTONIC, &pollstart))
+ break;
+ p = poll(fds, 1, timeout);
+ if (p == -1 && errno == EINTR) {
+ if (clock_gettime(CLOCK_MONOTONIC, &pollend))
+ break;
+
+ timespecsub(&pollend, &pollstart, &elapsed);
+ timeout -= (elapsed.tv_sec * 1000) +
+ (elapsed.tv_nsec / 1000000);
+ if (timeout < 1)
+ break;
goto again;
+ }
+
/*
* Otherwise, just ignore the error and let asr_run()
* catch the failure.