From f4209f7ea9c8d5b1c2f4ced117ffde75e1d84805 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 12 Apr 2009 11:46:22 +0200 Subject: [PATCH] Simplify Windows client to react to Ctrl-C always 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 | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/src/client/play.c b/src/client/play.c index 9e1a3e8f..8fa48fd4 100644 --- a/src/client/play.c +++ b/src/client/play.c @@ -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;