mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 06:13:31 +01:00
handle EINTR in compat_*threads.c
This commit is contained in:
parent
a52e549124
commit
ac5b70c700
@ -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>. */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user