Fix client not to hang when EOF on stdin overtakes C_EXECUTE
Player input may overtake batch file contents (well-known protocol
flaw, see doc/clients-howto for details). This includes EOF. When
that happens, the client closes standard input, sends an EOF cookie,
and continues reading output until the server closes the connection.
When it gets C_EXECUTE, it redirects input to the batch file. But it
then failed to read the batch file. The server waited forever for the
execute's EOF cookie, the client waited forever for the server closing
the connection.
Fix by stopping only reading from standard input. Broken in 8b7d0b91
,
v4.3.11.
Note that the EOF cookie still overtakes the batch file contents,
which makes the server interpret the input between the execute command
and the EOF as batch file, and the batch file contents as ordinary
input.
This commit is contained in:
parent
92ce7cf665
commit
2196ffd55c
1 changed files with 6 additions and 5 deletions
|
@ -473,10 +473,10 @@ play(int sock)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Want to read player input only when we don't need to send
|
* Want to read player input only when we don't need to send
|
||||||
* cookies, and we haven't hit EOF on fd 0, and INBUF can
|
* cookies, and INPUT_FD is still open, and INBUF can accept
|
||||||
* accept some.
|
* some.
|
||||||
*/
|
*/
|
||||||
if (!send_intr && !send_eof && !eof_fd0 && ring_space(&inbuf))
|
if (!send_intr && !send_eof && input_fd >= 0 && ring_space(&inbuf))
|
||||||
FD_SET(input_fd, &rdfd);
|
FD_SET(input_fd, &rdfd);
|
||||||
/* Want to send player input only when we have something */
|
/* Want to send player input only when we have something */
|
||||||
if (send_intr || send_eof || ring_len(&inbuf))
|
if (send_intr || send_eof || ring_len(&inbuf))
|
||||||
|
@ -503,7 +503,7 @@ play(int sock)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* read player input */
|
/* read player input */
|
||||||
if (FD_ISSET(input_fd, &rdfd)) {
|
if (input_fd >= 0 && FD_ISSET(input_fd, &rdfd)) {
|
||||||
n = recv_input(input_fd, &inbuf);
|
n = recv_input(input_fd, &inbuf);
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
perror("read stdin"); /* FIXME stdin misleading, could be execing */
|
perror("read stdin"); /* FIXME stdin misleading, could be execing */
|
||||||
|
@ -515,10 +515,11 @@ play(int sock)
|
||||||
if (input_fd) {
|
if (input_fd) {
|
||||||
/* execute done, switch back to fd 0 */
|
/* execute done, switch back to fd 0 */
|
||||||
close(input_fd);
|
close(input_fd);
|
||||||
input_fd = 0;
|
input_fd = eof_fd0 ? -1 : 0;
|
||||||
} else {
|
} else {
|
||||||
/* stop reading input, drain socket ring buffers */
|
/* stop reading input, drain socket ring buffers */
|
||||||
eof_fd0 = 1;
|
eof_fd0 = 1;
|
||||||
|
input_fd = -1;
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
sigaction(SIGINT, &sa, NULL);
|
sigaction(SIGINT, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue