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.
This commit is contained in:
parent
2bfe7a1198
commit
f4209f7ea9
1 changed files with 24 additions and 21 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue