Don't log out player when update aborts a command with pthreads
pthread.c's empth_select() returned -1 when empth_wakeup() interrupted select(). The failure then got propagated all the way up, and the player got logged out. Fix by returning 0 in that case. While there, retry on EINTR, to match LWP. Also clarify comments.
This commit is contained in:
parent
5073b022fd
commit
eea9e76bf8
3 changed files with 21 additions and 16 deletions
|
@ -160,8 +160,8 @@ void empth_yield(void);
|
||||||
* If FLAGS & EMPTH_FD_WRITE, wake up if FD is ready for output.
|
* If FLAGS & EMPTH_FD_WRITE, wake up if FD is ready for output.
|
||||||
* At most one thread may sleep on the same file descriptor.
|
* At most one thread may sleep on the same file descriptor.
|
||||||
* TIMEOUT, if non-null, limits the sleep time.
|
* TIMEOUT, if non-null, limits the sleep time.
|
||||||
* Return one when the FD is ready, zero on timeout, -1 on error with
|
* Return one when the FD is ready, zero on timeout or early wakeup by
|
||||||
* errno set.
|
* empth_wakeup(), -1 on error with errno set.
|
||||||
* Note: Currently, Empire sleeps only on network I/O, i.e. FD is a
|
* Note: Currently, Empire sleeps only on network I/O, i.e. FD is a
|
||||||
* socket. Implementations should not rely on that.
|
* socket. Implementations should not rely on that.
|
||||||
*/
|
*/
|
||||||
|
@ -169,7 +169,7 @@ int empth_select(int fd, int flags, struct timeval *timeout);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Awaken THREAD if it is sleeping in empth_select() or empth_sleep().
|
* Awaken THREAD if it is sleeping in empth_select() or empth_sleep().
|
||||||
* Note: This must not awaken threads sleeping in other functions.
|
* This does not awaken threads sleeping in other functions.
|
||||||
* Does not yield the processor.
|
* Does not yield the processor.
|
||||||
*/
|
*/
|
||||||
void empth_wakeup(empth_t *thread);
|
void empth_wakeup(empth_t *thread);
|
||||||
|
|
|
@ -110,11 +110,11 @@ io_close(struct iop *iop)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return number of bytes read on success, zero on timeout or EOF, -1
|
* Return number of bytes read on success, zero on timeout, early
|
||||||
* on error, with errno set appropriately. In particular, return -1
|
* wakeup or EOF, -1 on error, with errno set appropriately. In
|
||||||
* with errno set to EAGAIN or EWOULDBLOCK when no data is available
|
* particular, return -1 with errno set to EAGAIN or EWOULDBLOCK when
|
||||||
* for non-blocking input (WAITFORINPUT false). Use io_eof() to
|
* no data is available for non-blocking input (WAITFORINPUT false).
|
||||||
* distinguish timeout from EOF.
|
* Use io_eof() to distinguish timeout and early wakeup from EOF.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
io_input(struct iop *iop, int waitforinput)
|
io_input(struct iop *iop, int waitforinput)
|
||||||
|
|
|
@ -280,11 +280,13 @@ empth_select(int fd, int flags, struct timeval *timeout)
|
||||||
fd_set writemask;
|
fd_set writemask;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
int n;
|
int n;
|
||||||
|
empth_t *ctx;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
pthread_mutex_unlock(&mtx_ctxsw);
|
pthread_mutex_unlock(&mtx_ctxsw);
|
||||||
empth_status("select on %d for %d", fd, flags);
|
empth_status("select on %d for %d", fd, flags);
|
||||||
|
|
||||||
|
again:
|
||||||
FD_ZERO(&readmask);
|
FD_ZERO(&readmask);
|
||||||
FD_ZERO(&writemask);
|
FD_ZERO(&writemask);
|
||||||
if (flags & EMPTH_FD_READ)
|
if (flags & EMPTH_FD_READ)
|
||||||
|
@ -292,18 +294,21 @@ empth_select(int fd, int flags, struct timeval *timeout)
|
||||||
if (flags & EMPTH_FD_WRITE)
|
if (flags & EMPTH_FD_WRITE)
|
||||||
FD_SET(fd, &writemask);
|
FD_SET(fd, &writemask);
|
||||||
|
|
||||||
if (timeout) {
|
if (timeout)
|
||||||
tv = *timeout;
|
tv = *timeout;
|
||||||
timeout = &tv;
|
n = select(fd + 1, &readmask, &writemask, NULL, timeout ? &tv : NULL);
|
||||||
}
|
|
||||||
n = select(fd + 1, &readmask, &writemask, NULL, timeout);
|
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
if (errno == EINTR) /* go handle the signal */
|
ctx = pthread_getspecific(ctx_key);
|
||||||
|
if (ctx->wakeup) {
|
||||||
|
empth_status("select woken up");
|
||||||
|
res = 0;
|
||||||
|
} else if (errno == EINTR) {
|
||||||
empth_status("select broken by signal");
|
empth_status("select broken by signal");
|
||||||
else
|
goto again;
|
||||||
|
} else {
|
||||||
empth_status("select failed (%s)", strerror(errno));
|
empth_status("select failed (%s)", strerror(errno));
|
||||||
res = -1;
|
res = -1;
|
||||||
|
}
|
||||||
} else if (n == 0) {
|
} else if (n == 0) {
|
||||||
empth_status("select timed out");
|
empth_status("select timed out");
|
||||||
res = 0;
|
res = 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue