aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2015-01-21 12:18:11 -0500
committerNick Mathewson <nickm@torproject.org>2015-01-21 12:18:11 -0500
commitac5b70c700b211008853b5f212100a867f508dfd (patch)
tree53e83027711dd6f7dd4328a960efc615294dc926
parenta52e549124adb09ad0b49b7d2b5b3fb79bfe7aeb (diff)
downloadtor-ac5b70c700b211008853b5f212100a867f508dfd.tar.gz
tor-ac5b70c700b211008853b5f212100a867f508dfd.zip
handle EINTR in compat_*threads.c
-rw-r--r--src/common/compat_pthreads.c40
-rw-r--r--src/common/compat_threads.c55
2 files changed, 78 insertions, 17 deletions
diff --git a/src/common/compat_pthreads.c b/src/common/compat_pthreads.c
index f43480539f..188a91f68d 100644
--- a/src/common/compat_pthreads.c
+++ b/src/common/compat_pthreads.c
@@ -196,23 +196,37 @@ tor_cond_uninit(tor_cond_t *cond)
int
tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv)
{
+ int r;
if (tv == NULL) {
- return pthread_cond_wait(&cond->cond, &mutex->mutex) ? -1 : 0;
+ while (1) {
+ r = pthread_cond_wait(&cond->cond, &mutex->mutex);
+ if (r == EINTR) {
+ /* EINTR should be impossible according to POSIX, but POSIX, like the
+ * Pirate's Code, is apparently treated "more like what you'd call
+ * guidelines than actual rules." */
+ continue;
+ }
+ return r ? -1 : 0;
+ }
} else {
struct timespec ts;
struct timeval tvnow, tvsum;
- int r;
- gettimeofday(&tvnow, NULL);
- timeradd(tv, &tvnow, &tvsum);
- ts.tv_sec = tvsum.tv_sec;
- ts.tv_nsec = tvsum.tv_usec * 1000;
- r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts);
- if (r == 0)
- return 0;
- else if (r == ETIMEDOUT)
- return 1;
- else
- return -1;
+ while (1) {
+ gettimeofday(&tvnow, NULL);
+ timeradd(tv, &tvnow, &tvsum);
+ ts.tv_sec = tvsum.tv_sec;
+ ts.tv_nsec = tvsum.tv_usec * 1000;
+
+ r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts);
+ if (r == 0)
+ return 0;
+ else if (r == ETIMEDOUT)
+ return 1;
+ else if (r == EINTR)
+ continue;
+ else
+ return -1;
+ }
}
}
/** Wake up one of the waiters on <b>cond</b>. */
diff --git a/src/common/compat_threads.c b/src/common/compat_threads.c
index 79440070a2..3b79292cdb 100644
--- a/src/common/compat_threads.c
+++ b/src/common/compat_threads.c
@@ -88,12 +88,59 @@ in_main_thread(void)
return main_thread_id == tor_get_thread_id();
}
+#if defined(HAVE_EVENTFD) || defined(HAVE_PIPE)
+/* non-interruptable versions */
+static int
+write_ni(int fd, const void *buf, size_t n)
+{
+ int r;
+ again:
+ r = write(fd, buf, n);
+ if (r < 0 && errno == EINTR)
+ goto again;
+ return r;
+}
+static int
+read_ni(int fd, void *buf, size_t n)
+{
+ int r;
+ again:
+ r = read(fd, buf, n);
+ if (r < 0 && errno == EINTR)
+ goto again;
+ return r;
+}
+#endif
+
+/* non-interruptable versions */
+static int
+send_ni(int fd, const void *buf, size_t n, int flags)
+{
+ int r;
+ again:
+ r = send(fd, buf, n, flags);
+ if (r < 0 && errno == EINTR)
+ goto again;
+ return r;
+}
+
+static int
+recv_ni(int fd, void *buf, size_t n, int flags)
+{
+ int r;
+ again:
+ r = recv(fd, buf, n, flags);
+ if (r < 0 && errno == EINTR)
+ goto again;
+ return r;
+}
+
#ifdef HAVE_EVENTFD
static int
eventfd_alert(int fd)
{
uint64_t u = 1;
- int r = write(fd, (void*)&u, sizeof(u));
+ int r = write_ni(fd, (void*)&u, sizeof(u));
if (r < 0 && errno != EAGAIN)
return -1;
return 0;
@@ -103,7 +150,7 @@ static int
eventfd_drain(int fd)
{
uint64_t u = 0;
- int r = read(fd, (void*)&u, sizeof(u));
+ int r = read_ni(fd, (void*)&u, sizeof(u));
if (r < 0 && errno != EAGAIN)
return -1;
return 0;
@@ -136,7 +183,7 @@ pipe_drain(int fd)
static int
sock_alert(tor_socket_t fd)
{
- ssize_t r = send(fd, "x", 1, 0);
+ ssize_t r = send_ni(fd, "x", 1, 0);
if (r < 0 && !ERRNO_IS_EAGAIN(tor_socket_errno(fd)))
return -1;
return 0;
@@ -147,7 +194,7 @@ sock_drain(tor_socket_t fd)
{
char buf[32];
ssize_t r;
- while ((r = recv(fd, buf, sizeof(buf), 0)) >= 0)
+ while ((r = recv_ni(fd, buf, sizeof(buf), 0)) >= 0)
;
if (r == 0 || !ERRNO_IS_EAGAIN(tor_socket_errno(fd)))
return -1;