telnet: Fix infinite loop if local output generates SIGPIPE.
Instead of catching SIGPIPE and jumping out of the signal handler with longjmp, ignore it and handle write errors to the local output by exiting from there. I have changed the error message to mention the local output instead of NetBSD's wrong "Connection closed by foreign host". Write errors to the network were already handled by exiting immediately and this now applies to EPIPE too. The code assumed that SIGPIPE could only be generated by the network connection; if it was generated by the local output, it would longjmp out of the signal handler and write an error message which caused another SIGPIPE. PR: 19773 Obtained from: NetBSD MFC after: 1 week
This commit is contained in:
parent
6b22e476a5
commit
0637e80406
@ -2491,8 +2491,7 @@ tn(int argc, char *argv[])
|
||||
env_export("USER");
|
||||
}
|
||||
(void) call(status, "status", "notmuch", 0);
|
||||
if (setjmp(peerdied) == 0)
|
||||
telnet(user);
|
||||
telnet(user);
|
||||
(void) NetClose(net);
|
||||
ExitString("Connection closed by foreign host.\n",1);
|
||||
/*NOTREACHED*/
|
||||
|
@ -233,7 +233,6 @@ extern void
|
||||
SetNetTrace(char *); /* Function to change where debugging goes */
|
||||
|
||||
extern jmp_buf
|
||||
peerdied,
|
||||
toplevel; /* For error conditions. */
|
||||
|
||||
extern void
|
||||
|
@ -158,7 +158,7 @@ netflush(void)
|
||||
perror(hostname);
|
||||
(void)NetClose(net);
|
||||
ring_clear_mark(&netoring);
|
||||
longjmp(peerdied, -1);
|
||||
ExitString("Connection closed by foreign host.\n", 1);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
n = 0;
|
||||
|
@ -808,14 +808,6 @@ NetNonblockingIO(int fd, int onoff)
|
||||
* Various signal handling routines.
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static SIG_FUNC_RET
|
||||
deadpeer(int sig __unused)
|
||||
{
|
||||
setcommandmode();
|
||||
longjmp(peerdied, -1);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
SIG_FUNC_RET
|
||||
intr(int sig __unused)
|
||||
@ -884,7 +876,7 @@ sys_telnet_init(void)
|
||||
{
|
||||
(void) signal(SIGINT, intr);
|
||||
(void) signal(SIGQUIT, intr2);
|
||||
(void) signal(SIGPIPE, deadpeer);
|
||||
(void) signal(SIGPIPE, SIG_IGN);
|
||||
#ifdef SIGWINCH
|
||||
(void) signal(SIGWINCH, sendwin);
|
||||
#endif
|
||||
|
@ -146,7 +146,6 @@ unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
|
||||
#endif
|
||||
|
||||
jmp_buf toplevel;
|
||||
jmp_buf peerdied;
|
||||
|
||||
int flushline;
|
||||
int linemode;
|
||||
|
@ -111,7 +111,8 @@ init_terminal(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* Send as much data as possible to the terminal.
|
||||
* Send as much data as possible to the terminal, else exits if
|
||||
* it encounters a permanent failure when writing to the tty.
|
||||
*
|
||||
* Return value:
|
||||
* -1: No useful work done, data waiting to go out.
|
||||
@ -152,8 +153,19 @@ ttyflush(int drop)
|
||||
}
|
||||
ring_consumed(&ttyoring, n);
|
||||
}
|
||||
if (n < 0)
|
||||
if (n < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR) {
|
||||
return -1;
|
||||
} else {
|
||||
ring_consumed(&ttyoring, ring_full_count(&ttyoring));
|
||||
setconnmode(0);
|
||||
setcommandmode();
|
||||
NetClose(net);
|
||||
fprintf(stderr, "Write error on local output.\n");
|
||||
exit(1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (n == n0) {
|
||||
if (n0)
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user