]> git.pond.sub.org Git - empserver/commitdiff
Don't log out player when update aborts a command with pthreads
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 1 Mar 2009 10:34:50 +0000 (11:34 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 1 Mar 2009 12:04:48 +0000 (13:04 +0100)
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.

include/empthread.h
src/lib/empthread/io.c
src/lib/empthread/pthread.c

index 840192e570c437ba81290d8bed2c88ac4f0a83ae..d06efb10abf5f47c567470f3f9c8144b0f256ca7 100644 (file)
@@ -160,8 +160,8 @@ void empth_yield(void);
  * If FLAGS & EMPTH_FD_WRITE, wake up if FD is ready for output.
  * At most one thread may sleep on the same file descriptor.
  * TIMEOUT, if non-null, limits the sleep time.
- * Return one when the FD is ready, zero on timeout, -1 on error with
- * errno set.
+ * Return one when the FD is ready, zero on timeout or early wakeup by
+ * empth_wakeup(), -1 on error with errno set.
  * Note: Currently, Empire sleeps only on network I/O, i.e. FD is a
  * 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().
- * Note: This must not awaken threads sleeping in other functions.
+ * This does not awaken threads sleeping in other functions.
  * Does not yield the processor.
  */
 void empth_wakeup(empth_t *thread);
index 5e2984eeda704352fc29c321a95432d3d0fb3ebb..5bbce8d9761eeec09437520c7ad7ba63e40d3243 100644 (file)
@@ -110,11 +110,11 @@ io_close(struct iop *iop)
 }
 
 /*
- * Return number of bytes read on success, zero on timeout or EOF, -1
- * on error, with errno set appropriately.  In particular, return -1
- * with errno set to EAGAIN or EWOULDBLOCK when no data is available
- * for non-blocking input (WAITFORINPUT false).  Use io_eof() to
- * distinguish timeout from EOF.
+ * Return number of bytes read on success, zero on timeout, early
+ * wakeup or EOF, -1 on error, with errno set appropriately.  In
+ * particular, return -1 with errno set to EAGAIN or EWOULDBLOCK when
+ * no data is available for non-blocking input (WAITFORINPUT false).
+ * Use io_eof() to distinguish timeout and early wakeup from EOF.
  */
 int
 io_input(struct iop *iop, int waitforinput)
index 9c1163ff5fc888b793f06c64f55df88c2d7c015f..fb1e09a93044992224f710dbc3d82aedbc4d392f 100644 (file)
@@ -280,11 +280,13 @@ empth_select(int fd, int flags, struct timeval *timeout)
     fd_set writemask;
     struct timeval tv;
     int n;
+    empth_t *ctx;
     int res = 0;
 
     pthread_mutex_unlock(&mtx_ctxsw);
     empth_status("select on %d for %d", fd, flags);
 
+again:
     FD_ZERO(&readmask);
     FD_ZERO(&writemask);
     if (flags & EMPTH_FD_READ)
@@ -292,18 +294,21 @@ empth_select(int fd, int flags, struct timeval *timeout)
     if (flags & EMPTH_FD_WRITE)
        FD_SET(fd, &writemask);
 
-    if (timeout) {
+    if (timeout)
        tv = *timeout;
-       timeout = &tv;
-    }
-    n = select(fd + 1, &readmask, &writemask, NULL, timeout);
-
+    n = select(fd + 1, &readmask, &writemask, NULL, timeout ? &tv : NULL);
     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");
-        else
+           goto again;
+       } else {
            empth_status("select failed (%s)", strerror(errno));
-       res = -1;
+           res = -1;
+       }
     } else if (n == 0) {
        empth_status("select timed out");
        res = 0;