Bug 180146

Summary: /bin/sh: Early SIGWINCH can end process
Product: Base System Reporter: Grant Watson <grant_watson>
Component: binAssignee: Jilles Tjoelker <jilles>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 9.1-RELEASE   
Hardware: Any   
OS: Any   

Description Grant Watson 2013-07-01 04:10:00 UTC
There appears to be a race condition in /bin/sh where receiving
SIGWINCH too early will cause the process to end.  Bugs ports/178194
and ports/178651, which I filed, are occurrences of this bug.

How-To-Repeat: Way to Reproduce #1:

Install termit and paste the following into ~/.config/termit/rc.lua:

    defaults = {
        showScrollbar = false,
        hideMenubar = true
    }
    setOptions(defaults)

Then run "termit -e /bin/sh".  Running "termit -e 'truss -o shlog.txt /bin/sh'" does not surpress the bug for me.

Way to Reproduce #2:

Install the awesome window manager, create a user whose shell is /bin/sh, and ensure that this user does not have a ~/.config/awesome/rc.lua file that would override the default configuration.

Log in as this user.  Left click the box in the upper-right corner of the screen to switch to a tiling layout.  Press super+return (that is, windows+return) four or five times; each time an xterm should open.  Many will close, but one or two may remain open.  Running "truss xterm -e /bin/sh" does not surpress the bug for me, but running truss between xterm and sh does.
Comment 1 Alex Kozlov freebsd_committer freebsd_triage 2013-10-11 05:19:08 UTC
Responsible Changed
From-To: freebsd-bugs->jilles

Over to maintainer.
Comment 2 Jilles Tjoelker freebsd_committer freebsd_triage 2013-10-11 11:44:55 UTC
In PR bin/180146, you wrote:
> There appears to be a race condition in /bin/sh where receiving
> SIGWINCH too early will cause the process to end. Bugs ports/178194
> and ports/178651, which I filed, are occurrences of this bug.

Although I cannot reproduce this bug using the termit reproducer, I can
imagine libedit contains this kind of bug since it is of a low quality
in general (see also
http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/169773 ).

Perhaps the below patch will work around your issue (while delaying the
response to a true SIGWINCH until <Enter> is pressed).

commit 548c429eea82f483d56181115451f70146d9b948
Author: Jilles Tjoelker <jilles@stack.nl>
Date:   Sun Sep 1 18:22:24 2013 +0200

    sh: Enable system call restart for the default SIGWINCH handler.
    
    This makes it apply later than it should but avoids libedit bugs.

diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index 3fc8566..73e156b 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -260,6 +260,7 @@ setsignal(int signo)
 	struct sigaction sa;
 	char *t;
 
+	sa.sa_flags = 0;
 	if ((t = trap[signo]) == NULL)
 		action = S_DFL;
 	else if (*t != '\0')
@@ -297,6 +298,7 @@ setsignal(int signo)
 		case SIGWINCH:
 			if (rootshell && iflag)
 				action = S_CATCH;
+			sa.sa_flags |= SA_RESTART;
 			break;
 #endif
 		}
@@ -334,7 +336,6 @@ setsignal(int signo)
 	}
 	*t = action;
 	sa.sa_handler = sigact;
-	sa.sa_flags = 0;
 	sigemptyset(&sa.sa_mask);
 	sigaction(signo, &sa, NULL);
 }

-- 
Jilles Tjoelker
Comment 3 dfilter service freebsd_committer freebsd_triage 2014-01-14 22:56:38 UTC
Author: jilles
Date: Tue Jan 14 22:56:25 2014
New Revision: 260654
URL: http://svnweb.freebsd.org/changeset/base/260654

Log:
  sh: Remove SIGWINCH handler and just check for resize before every read.
  
  The SIGWINCH handler triggers breakage in libedit which is hard to fix; see
  PR bin/169773.
  
  Also, window size changes while a program is in foreground (and it rather
  than sh will receive SIGWINCH) will now be picked up automatically.
  
  Downside: it is now certain that a resize is only processed after pressing
  <Enter>. If libedit is fixed, sh will most likely have to be changed also.
  
  PR:		bin/180146

Modified:
  head/bin/sh/input.c
  head/bin/sh/trap.c
  head/bin/sh/trap.h

Modified: head/bin/sh/input.c
==============================================================================
--- head/bin/sh/input.c	Tue Jan 14 22:46:23 2014	(r260653)
+++ head/bin/sh/input.c	Tue Jan 14 22:56:25 2014	(r260654)
@@ -162,20 +162,16 @@ preadfd(void)
 	int nr;
 	parsenextc = parsefile->buf;
 
-#ifndef NO_HISTORY
-	if (el != NULL && gotwinch) {
-		gotwinch = 0;
-		el_resize(el);
-	}
-#endif
 retry:
 #ifndef NO_HISTORY
 	if (parsefile->fd == 0 && el) {
 		static const char *rl_cp;
 		static int el_len;
 
-		if (rl_cp == NULL)
+		if (rl_cp == NULL) {
+			el_resize(el);
 			rl_cp = el_gets(el, &el_len);
+		}
 		if (rl_cp == NULL)
 			nr = el_len == 0 ? 0 : -1;
 		else {

Modified: head/bin/sh/trap.c
==============================================================================
--- head/bin/sh/trap.c	Tue Jan 14 22:46:23 2014	(r260653)
+++ head/bin/sh/trap.c	Tue Jan 14 22:56:25 2014	(r260654)
@@ -80,7 +80,6 @@ static char *volatile trap[NSIG];	/* tra
 static volatile sig_atomic_t gotsig[NSIG];
 				/* indicates specified signal received */
 static int ignore_sigchld;	/* Used while handling SIGCHLD traps. */
-volatile sig_atomic_t gotwinch;
 static int last_trapsig;
 
 static int exiting;		/* exitshell() has been called */
@@ -293,12 +292,6 @@ setsignal(int signo)
 				action = S_IGN;
 			break;
 #endif
-#ifndef NO_HISTORY
-		case SIGWINCH:
-			if (rootshell && iflag)
-				action = S_CATCH;
-			break;
-#endif
 		}
 	}
 
@@ -400,11 +393,6 @@ onsig(int signo)
 		gotsig[signo] = 1;
 		pendingsig = signo;
 	}
-
-#ifndef NO_HISTORY
-	if (signo == SIGWINCH)
-		gotwinch = 1;
-#endif
 }
 
 
@@ -490,9 +478,6 @@ setinteractive(int on)
 	setsignal(SIGINT);
 	setsignal(SIGQUIT);
 	setsignal(SIGTERM);
-#ifndef NO_HISTORY
-	setsignal(SIGWINCH);
-#endif
 	is_interactive = on;
 }
 

Modified: head/bin/sh/trap.h
==============================================================================
--- head/bin/sh/trap.h	Tue Jan 14 22:46:23 2014	(r260653)
+++ head/bin/sh/trap.h	Tue Jan 14 22:56:25 2014	(r260654)
@@ -36,7 +36,6 @@
 extern volatile sig_atomic_t pendingsig;
 extern volatile sig_atomic_t pendingsig_waitcmd;
 extern int in_dotrap;
-extern volatile sig_atomic_t gotwinch;
 
 void clear_traps(void);
 int have_traps(void);
_______________________________________________
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 4 Jilles Tjoelker freebsd_committer freebsd_triage 2014-02-04 22:24:45 UTC
State Changed
From-To: open->patched

I have applied a workaround for libedit breakage in 11-current 
in SVN r260654.
Comment 5 Jilles Tjoelker freebsd_committer freebsd_triage 2014-06-06 13:51:14 UTC
This change was merged to stable/10 in SVN r262951. No MFC to older branches is planned.