Bug 19773

Summary: [patch] telnet(1) infinite loop depending on how fds are closed
Product: Base System Reporter: joelh <joelh>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.0-STABLE   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
file.diff none

Description joelh 2000-07-08 03:00:01 UTC
The telnet client can get into an infinite loop if the pipe going to
stdout and stderr is closed before the pipe going to stdin.  This is
because, on a SIGPIPE, it will assume that the remote has closed its
connection.  It longjmp()'s out of the signal handler, and reports this
to the user on stdout or stderr (not sure which, doesn't really matter),
generating another SIGPIPE.  Now, that SIGPIPE will try the same longjmp.
telnet tries to report again, gets another SIGPIPE... ad infinitum.

Fix: Here's the fix for crypto/telnet/telnet/sys_bsd.c.  I haven't looked at the
other telnets, but I would assume they would be similar.  Caveat: I've
tested this precisely twice.
How-To-Repeat: 
Compile and run the following program.  (I'm not sure how necessary the
sleeps are, and this has a few minor bugs, but it demonstrates the
problem.)  After the process closes the pipe from "me->telnet", then the
telnet process (find it with top or ps, sorry) will go into the
aforementioned infinite loop.  Note that the telnet sticks around after
the calling program exits; find it with top or ps and kill it yourself.

#include <stdio.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    int topipe[2];
    int frompipe[2];
    pipe(&topipe);
    pipe(&frompipe);
    if (!fork()) {
	close(topipe[1]);
	close(frompipe[0]);
	dup2(topipe[0], 0);
	dup2(frompipe[1], 1);
	dup2(frompipe[1], 2);
	execlp("/usr/bin/telnet", "telnet", "localhost", NULL);
	abort();
    }
    close(topipe[0]);
    close(frompipe[1]);
    printf("forked\n");
    sleep(5);
    printf("closing telnet->me\n");
    close(frompipe[0]);
    sleep(3);
    printf("closing me->telnet\n");
    close(topipe[1]);
    sleep(2);
    printf("bye\n");
    exit(0);
}
Comment 1 Mike Barcroft freebsd_committer freebsd_triage 2001-07-22 06:01:47 UTC
State Changed
From-To: open->feedback


Does this problem still occur in newer versions of FreeBSD, 
such as 4.3-RELEASE?
Comment 2 Mike Barcroft freebsd_committer freebsd_triage 2001-07-23 17:23:23 UTC
Adding to Audit-Trail.

----- Forwarded message from Joel Ray Holveck <joelh@gnu.org> -----

Delivered-To: mike@freebsd.org
To: <mike@FreeBSD.org>
Cc: freebsd-bugs@FreeBSD.org
Subject: Re: bin/19773: [PATCH] telnet infinite loop depending on how fds are closed
From: Joel Ray Holveck <joelh@gnu.org>
Precedence: first-class
Date: 23 Jul 2001 00:41:48 -0700
In-Reply-To: <mike@FreeBSD.org>'s message of "Sat, 21 Jul 2001 22:02:02 -0700 (PDT)"
X-Mailer: Gnus v5.7/Emacs 20.7

> Synopsis: [PATCH] telnet infinite loop depending on how fds are closed
> State-Changed-From-To: open->feedback
> State-Changed-By: mike
> State-Changed-When: Sat Jul 21 22:01:47 PDT 2001
> State-Changed-Why: 
> Does this problem still occur in newer versions of FreeBSD,
> such as 4.3-RELEASE?
> http://www.FreeBSD.org/cgi/query-pr.cgi?pr=19773

I used the reproduction code in the bug report to test it under
4.3-STABLE, and it does still occur.

(There's technically a bug in the reproduction code-- the args to pipe
shouldn't have &s-- but the repro code still does its job for most
compilers.)

joelh

-- 
Joel Ray Holveck - joelh@gnu.org
   Fourth law of programming:
   Anything that can go wrong wi
sendmail: segmentation violation - core dumped

----- End forwarded message -----
Comment 3 Mike Barcroft freebsd_committer freebsd_triage 2001-07-24 00:55:30 UTC
State Changed
From-To: feedback->suspended


This is still a problem in 4.3-STABLE.  Awaiting fix and committer.
Comment 4 Johan Karlsson freebsd_committer freebsd_triage 2002-08-23 02:16:24 UTC
Responsible Changed
From-To: freebsd-bugs->markm

Let our telnet maintainer have a look at this.
Comment 5 Joel Ray Holveck 2003-08-16 20:34:34 UTC
Just for fun, I retested this under FreeBSD 5.1-STABLE.  It still has
the same problem.

-- 
Joel Ray Holveck - joelh@piquan.org
   Fourth law of programming:
   Anything that can go wrong wi
sendmail: segmentation violation - core dumped
Comment 6 Andy_Nissen 2006-09-10 20:48:08 UTC
I ran into this problem recently with a similar script:

cat << __EOF__ > telnet_spin.py
#! /usr/contrib/bin/python
import os

# Change IP and port to suit needs - This happens to work in my
configuration.
CMD =3D ['/usr/bin/telnet', '10.69.181.121', '80']
GET =3D 'GET http://www.example.com HTTP/1.0\n\n'

stdin, stdout, stderr =3D os.popen3(CMD)
stdin.write(GET)
__EOF__

This is on FreeBSD 6.0-RELEASE.  My fix is comparable, but also catches =
the
longjmp from netflush.

__FBSDID("$FreeBSD: src/contrib/telnet/telnet/commands.c,v 1.35 =
2005/02/28
12:46:52 tobez Exp $");

***************

*** 2494,2499 ****
--- 2494,2507 ----
      if (setjmp(peerdied) =3D=3D 0)
        telnet(user);
      (void) NetClose(net);
+=20
+     /*
+      *  Since ExitString does a write, if SIGPIPE is left going to
deadpeer, we
+      *  may end up in a loop.   Since longjump restores the signal =
mask,
we break
+      *  the tie here.
+      */
+     signal(SIGPIPE, SIG_IGN);
+=20
      ExitString("Connection closed by foreign host.\n",1);
      /*NOTREACHED*/
   fail:

Andy
Comment 7 jfesler 2008-02-15 19:31:57 UTC
Still happens in 6.3

Easiest and most painfully frequent way I run into it, is :

ssh somehost telnet otherhost port

And then killing the SSH process.

I've worked around it by calling:
ssh somehost 'ssh -c "limit -t 10 ; telnet otherhost port"'

so that when (not if) the process spins, it gets killed  
automatically.  Also, I try to gracefully tell telnet to close (send  
^], close) first - except when debugging this cleanup doesn't always  
get called.
Comment 8 dfilter service freebsd_committer freebsd_triage 2010-04-30 20:53:18 UTC
Author: jilles
Date: Fri Apr 30 19:52:35 2010
New Revision: 207449
URL: http://svn.freebsd.org/changeset/base/207449

Log:
  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

Modified:
  head/contrib/telnet/telnet/commands.c
  head/contrib/telnet/telnet/externs.h
  head/contrib/telnet/telnet/network.c
  head/contrib/telnet/telnet/sys_bsd.c
  head/contrib/telnet/telnet/telnet.c
  head/contrib/telnet/telnet/terminal.c

Modified: head/contrib/telnet/telnet/commands.c
==============================================================================
--- head/contrib/telnet/telnet/commands.c	Fri Apr 30 19:40:37 2010	(r207448)
+++ head/contrib/telnet/telnet/commands.c	Fri Apr 30 19:52:35 2010	(r207449)
@@ -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*/

Modified: head/contrib/telnet/telnet/externs.h
==============================================================================
--- head/contrib/telnet/telnet/externs.h	Fri Apr 30 19:40:37 2010	(r207448)
+++ head/contrib/telnet/telnet/externs.h	Fri Apr 30 19:52:35 2010	(r207449)
@@ -233,7 +233,6 @@ extern void
     SetNetTrace(char *);	/* Function to change where debugging goes */
 
 extern jmp_buf
-    peerdied,
     toplevel;		/* For error conditions. */
 
 extern void

Modified: head/contrib/telnet/telnet/network.c
==============================================================================
--- head/contrib/telnet/telnet/network.c	Fri Apr 30 19:40:37 2010	(r207448)
+++ head/contrib/telnet/telnet/network.c	Fri Apr 30 19:52:35 2010	(r207449)
@@ -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;

Modified: head/contrib/telnet/telnet/sys_bsd.c
==============================================================================
--- head/contrib/telnet/telnet/sys_bsd.c	Fri Apr 30 19:40:37 2010	(r207448)
+++ head/contrib/telnet/telnet/sys_bsd.c	Fri Apr 30 19:52:35 2010	(r207449)
@@ -809,14 +809,6 @@ NetNonblockingIO(int fd, int onoff)
  */
 
 /* 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

Modified: head/contrib/telnet/telnet/telnet.c
==============================================================================
--- head/contrib/telnet/telnet/telnet.c	Fri Apr 30 19:40:37 2010	(r207448)
+++ head/contrib/telnet/telnet/telnet.c	Fri Apr 30 19:52:35 2010	(r207449)
@@ -146,7 +146,6 @@ unsigned char telopt_environ = TELOPT_NE
 #endif
 
 jmp_buf	toplevel;
-jmp_buf	peerdied;
 
 int	flushline;
 int	linemode;

Modified: head/contrib/telnet/telnet/terminal.c
==============================================================================
--- head/contrib/telnet/telnet/terminal.c	Fri Apr 30 19:40:37 2010	(r207448)
+++ head/contrib/telnet/telnet/terminal.c	Fri Apr 30 19:52:35 2010	(r207449)
@@ -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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 9 Jilles Tjoelker freebsd_committer freebsd_triage 2010-04-30 21:06:48 UTC
State Changed
From-To: suspended->patched

Fixed in 9-CURRENT. 


Comment 10 Jilles Tjoelker freebsd_committer freebsd_triage 2010-04-30 21:06:48 UTC
Responsible Changed
From-To: markm->jilles

Take.
Comment 11 dfilter service freebsd_committer freebsd_triage 2010-05-07 21:59:08 UTC
Author: jilles
Date: Fri May  7 20:58:50 2010
New Revision: 207758
URL: http://svn.freebsd.org/changeset/base/207758

Log:
  MFC r207449: 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

Modified:
  stable/8/contrib/telnet/telnet/commands.c
  stable/8/contrib/telnet/telnet/externs.h
  stable/8/contrib/telnet/telnet/network.c
  stable/8/contrib/telnet/telnet/sys_bsd.c
  stable/8/contrib/telnet/telnet/telnet.c
  stable/8/contrib/telnet/telnet/terminal.c
Directory Properties:
  stable/8/contrib/telnet/   (props changed)

Modified: stable/8/contrib/telnet/telnet/commands.c
==============================================================================
--- stable/8/contrib/telnet/telnet/commands.c	Fri May  7 20:46:22 2010	(r207757)
+++ stable/8/contrib/telnet/telnet/commands.c	Fri May  7 20:58:50 2010	(r207758)
@@ -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*/

Modified: stable/8/contrib/telnet/telnet/externs.h
==============================================================================
--- stable/8/contrib/telnet/telnet/externs.h	Fri May  7 20:46:22 2010	(r207757)
+++ stable/8/contrib/telnet/telnet/externs.h	Fri May  7 20:58:50 2010	(r207758)
@@ -233,7 +233,6 @@ extern void
     SetNetTrace(char *);	/* Function to change where debugging goes */
 
 extern jmp_buf
-    peerdied,
     toplevel;		/* For error conditions. */
 
 extern void

Modified: stable/8/contrib/telnet/telnet/network.c
==============================================================================
--- stable/8/contrib/telnet/telnet/network.c	Fri May  7 20:46:22 2010	(r207757)
+++ stable/8/contrib/telnet/telnet/network.c	Fri May  7 20:58:50 2010	(r207758)
@@ -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;

Modified: stable/8/contrib/telnet/telnet/sys_bsd.c
==============================================================================
--- stable/8/contrib/telnet/telnet/sys_bsd.c	Fri May  7 20:46:22 2010	(r207757)
+++ stable/8/contrib/telnet/telnet/sys_bsd.c	Fri May  7 20:58:50 2010	(r207758)
@@ -809,14 +809,6 @@ NetNonblockingIO(int fd, int onoff)
  */
 
 /* 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

Modified: stable/8/contrib/telnet/telnet/telnet.c
==============================================================================
--- stable/8/contrib/telnet/telnet/telnet.c	Fri May  7 20:46:22 2010	(r207757)
+++ stable/8/contrib/telnet/telnet/telnet.c	Fri May  7 20:58:50 2010	(r207758)
@@ -146,7 +146,6 @@ unsigned char telopt_environ = TELOPT_NE
 #endif
 
 jmp_buf	toplevel;
-jmp_buf	peerdied;
 
 int	flushline;
 int	linemode;

Modified: stable/8/contrib/telnet/telnet/terminal.c
==============================================================================
--- stable/8/contrib/telnet/telnet/terminal.c	Fri May  7 20:46:22 2010	(r207757)
+++ stable/8/contrib/telnet/telnet/terminal.c	Fri May  7 20:58:50 2010	(r207758)
@@ -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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 12 dfilter service freebsd_committer freebsd_triage 2010-05-13 16:28:54 UTC
Author: jilles
Date: Thu May 13 15:28:34 2010
New Revision: 208029
URL: http://svn.freebsd.org/changeset/base/208029

Log:
  MFC r207449: 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

Modified:
  stable/7/contrib/telnet/telnet/commands.c
  stable/7/contrib/telnet/telnet/externs.h
  stable/7/contrib/telnet/telnet/network.c
  stable/7/contrib/telnet/telnet/sys_bsd.c
  stable/7/contrib/telnet/telnet/telnet.c
  stable/7/contrib/telnet/telnet/terminal.c
Directory Properties:
  stable/7/contrib/telnet/   (props changed)

Modified: stable/7/contrib/telnet/telnet/commands.c
==============================================================================
--- stable/7/contrib/telnet/telnet/commands.c	Thu May 13 12:08:11 2010	(r208028)
+++ stable/7/contrib/telnet/telnet/commands.c	Thu May 13 15:28:34 2010	(r208029)
@@ -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*/

Modified: stable/7/contrib/telnet/telnet/externs.h
==============================================================================
--- stable/7/contrib/telnet/telnet/externs.h	Thu May 13 12:08:11 2010	(r208028)
+++ stable/7/contrib/telnet/telnet/externs.h	Thu May 13 15:28:34 2010	(r208029)
@@ -233,7 +233,6 @@ extern void
     SetNetTrace(char *);	/* Function to change where debugging goes */
 
 extern jmp_buf
-    peerdied,
     toplevel;		/* For error conditions. */
 
 extern void

Modified: stable/7/contrib/telnet/telnet/network.c
==============================================================================
--- stable/7/contrib/telnet/telnet/network.c	Thu May 13 12:08:11 2010	(r208028)
+++ stable/7/contrib/telnet/telnet/network.c	Thu May 13 15:28:34 2010	(r208029)
@@ -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;

Modified: stable/7/contrib/telnet/telnet/sys_bsd.c
==============================================================================
--- stable/7/contrib/telnet/telnet/sys_bsd.c	Thu May 13 12:08:11 2010	(r208028)
+++ stable/7/contrib/telnet/telnet/sys_bsd.c	Thu May 13 15:28:34 2010	(r208029)
@@ -809,14 +809,6 @@ NetNonblockingIO(int fd, int onoff)
  */
 
 /* 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

Modified: stable/7/contrib/telnet/telnet/telnet.c
==============================================================================
--- stable/7/contrib/telnet/telnet/telnet.c	Thu May 13 12:08:11 2010	(r208028)
+++ stable/7/contrib/telnet/telnet/telnet.c	Thu May 13 15:28:34 2010	(r208029)
@@ -146,7 +146,6 @@ unsigned char telopt_environ = TELOPT_NE
 #endif
 
 jmp_buf	toplevel;
-jmp_buf	peerdied;
 
 int	flushline;
 int	linemode;

Modified: stable/7/contrib/telnet/telnet/terminal.c
==============================================================================
--- stable/7/contrib/telnet/telnet/terminal.c	Thu May 13 12:08:11 2010	(r208028)
+++ stable/7/contrib/telnet/telnet/terminal.c	Thu May 13 15:28:34 2010	(r208029)
@@ -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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 13 Jilles Tjoelker freebsd_committer freebsd_triage 2010-05-13 16:40:37 UTC
Responsible Changed
From-To: jilles->freebsd-bugs

This is fixed in 7.x/8.x/9.x. I'm not interested in 6.x.
Comment 14 Maxim Konovalov freebsd_committer freebsd_triage 2010-09-07 12:34:49 UTC
State Changed
From-To: patched->closed

It looks like the fix was merged to all supported branches.  Close the PR.