]> git.pond.sub.org Git - empserver/commitdiff
Simplify Windows client to react to Ctrl-C always
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 12 Apr 2009 09:46:22 +0000 (11:46 +0200)
committerMarkus Armbruster <armbru@pond.sub.org>
Mon, 30 Nov 2009 18:43:50 +0000 (19:43 +0100)
When select() gets interrupted by SIGINT while a handler is active
without SA_RESTART, it returns immediately with EINTR.  w32_select()
did that only while it waited for standard input to become ready for
reading.  This isn't the case when:

* The client has already received EOF on standard input.  But then the
  action is SIG_DFL, so there was no problem.

* Reading standard input is suspended until the server drains the
  input buffer.  Then reaction to Ctrl-C got delayed until the socket
  got ready, and w32_select() returned normally.  Harmless, because
  the reaction merely appends to the input buffer.

Change w32_select() to match select()'s behavior anyway.

src/client/play.c

index 9e1a3e8f06fbd6f9bd73b8e73da9d04d15545cac..8fa48fd49622a8930467654a4af189e2b3c138aa 100644 (file)
@@ -67,7 +67,7 @@ static HANDLE bounce_empty;
  * stdin thread and is available for recv_input
  */
 static HANDLE bounce_full;
- /* Ctrl-C (SIGINT) was detected, generate EINTR for the w32_select() */
+/* Ctrl-C (SIGINT) was detected, generate EINTR for the w32_select() */
 static HANDLE ctrl_c_event;
 static int bounce_status, bounce_error;
 
@@ -184,24 +184,31 @@ w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval*
 {
     HANDLE handles[3];
     SOCKET sock;
-    int result, s_result, num_handles = 0;
+    int inp, result, s_result, num_handles;
     struct timeval tv_time = {0, 0};
     fd_set rdfd2;
 
-    if (rdfd->fd_count > 1) {
-       sock = rdfd->fd_array[1];
-       if (rdfd->fd_array[0])
-           handles[num_handles++] = (HANDLE)rdfd->fd_array[0];
-       else {
-           handles[num_handles++] = ctrl_c_event;
-           handles[num_handles++] = bounce_full;
-       }
-    } else {
-       assert(rdfd->fd_count == 1);
+    switch (rdfd->fd_count) {
+    case 1:
+       inp = -1;
        sock = rdfd->fd_array[0];
+       break;
+    case 2:
+       inp = rdfd->fd_array[0];
+       sock = rdfd->fd_array[1];
+       break;
+    default:
+       assert(0);
     }
-    assert(wrfd->fd_count == 0 ||
-          (wrfd->fd_count == 1 && wrfd->fd_array[0] == sock));
+
+    assert(wrfd->fd_count == 0
+          || (wrfd->fd_count == 1 && wrfd->fd_array[0] == sock));
+    assert(inp < 0 || inp == input_fd);
+
+    num_handles = 0;
+    handles[num_handles++] = ctrl_c_event;
+    if (inp >= 0)
+       handles[num_handles++] = inp ? (HANDLE)inp : bounce_full;
     /* always wait on the socket */
     handles[num_handles++] = WSACreateEvent();
 
@@ -220,7 +227,7 @@ w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval*
     }
     WSACloseEvent(handles[num_handles - 1]);
 
-    if (num_handles == 3 && result == WAIT_OBJECT_0) {
+    if (result == WAIT_OBJECT_0) {
        errno = EINTR;
        return -1;
     }
@@ -235,12 +242,8 @@ w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval*
     }
 
     *rdfd = rdfd2;
-    if (num_handles == 3 && result == WAIT_OBJECT_0 + 1) {
-       FD_SET((SOCKET)0, rdfd);
-       s_result++;
-    }
-    if (num_handles == 2 && result == WAIT_OBJECT_0) {
-       FD_SET((SOCKET)handles[0], rdfd);
+    if (inp >= 0 && result == WAIT_OBJECT_0 + 1) {
+       FD_SET((SOCKET)inp, rdfd);
        s_result++;
     }
     return s_result;