Bug 13463

Summary: /bin/sh does not handle interrupts correctly (?)
Product: Base System Reporter: Tim Vanderhoek <hoek>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.0-CURRENT   
Hardware: Any   
OS: Any   

Description Tim Vanderhoek 1999-08-30 05:10:00 UTC
$ while :; do echo -n ; done
^C
$ while :; do echo -n ; done
^C
$ while :; do echo -n ; done
sh in malloc(): warning: recursive call.
sh in malloc(): warning: recursive call.
Segmentation fault (core dumped)

Fix: 

Hope you get lucky?
How-To-Repeat: 
As above, enter "while :; do echo -n ; done" repeatedly and 
interrupt it.  When it does die, it dies immediately when the last
while command is entered (ie. not at ^C).

I suspect this is a more generic problem than this instance of it suggests.

Sometimes 20 or more iterations must be completed before it finally
segvs.  Sometimes far fewer...
Comment 1 Sheldon Hearn 1999-08-30 09:06:32 UTC
On Sun, 29 Aug 1999 21:00:58 MST, Tim Vanderhoek wrote:

> $ while :; do echo -n ; done
> sh in malloc(): warning: recursive call.
> sh in malloc(): warning: recursive call.
> Segmentation fault (core dumped)

This looks weird.

Program terminated with signal 11, Segmentation fault.
#0  0x805d644 in yywrap ()
(gdb) back
#0  0x805d644 in yywrap ()
#1  0x805d681 in yywrap ()
#2  0x805db05 in history ()
#3  0x8051e3d in preadbuffer () at /usr/src/bin/sh/input.c:296
#4  0x8058765 in xxreadtoken () at /usr/src/bin/sh/parser.c:776
#5  0x80585b7 in readtoken () at /usr/src/bin/sh/parser.c:693
#6  0x805762d in parsecmd (interact=1) at /usr/src/bin/sh/parser.c:145
#7  0x80545b5 in cmdloop (top=1) at /usr/src/bin/sh/main.c:240
#8  0x805452f in main (argc=1, argv=0xbfbfd668) at
/usr/src/bin/sh/main.c:203

How on earth does yywrap recurse on itself like that?

/usr/src/usr.bin/lex/lib/libyywrap.c:
int yywrap()
	{
	return 1;
	}

By the way, I can't reproduce the problem if I compile with -DDEBUG=2.

Ciao,
Sheldon.
Comment 2 Tim Vanderhoek 1999-08-30 18:01:16 UTC
On Mon, Aug 30, 1999 at 10:06:32AM +0200, Sheldon Hearn wrote:
> 
> How on earth does yywrap recurse on itself like that?

This is what I get if I set malloc_options to AX,

Program terminated with signal 6, Abort trap.
#0  0x806fbd0 in kill ()
(gdb) bt
#0  0x806fbd0 in kill ()
#1  0x808e568 in abort ()
#2  0x808d0db in isatty ()
#3  0x808d0fb in isatty ()
#4  0x808e124 in malloc ()
#5  0x8059ff2 in yywrap ()
#6  0x805a042 in yywrap ()
#7  0x805a5db in history ()
#8  0x8050420 in preadbuffer () at /usr/src/bin/sh/input.c:297
#9  0x8055cf5 in xxreadtoken () at /usr/src/bin/sh/parser.c:776
#10 0x8055b11 in readtoken () at /usr/src/bin/sh/parser.c:693
#11 0x8054da9 in parsecmd (interact=1) at /usr/src/bin/sh/parser.c:145
#12 0x805254b in cmdloop (top=1) at /usr/src/bin/sh/main.c:244
#13 0x80524d3 in main (argc=1, argv=0xbfbfdb48) at
/usr/src/bin/sh/main.c:207
#14 0x80480ed in _start ()
(gdb) print suppressint
$1 = 1

I don't know if that value for suppressint is correct.  I tend to
suspect it is.

It's got to be something to do with the signal that starts scrambling
memory.  Have a look at this:

# while :; do echo -n ; done
^C
# asdfasdfasdfjkl
asdfasdfasdfjkl: not found
# while :; do echo -n ; done
^C
# asdfasdfasdfasd
asdfasdfasdfasd: not found
# while :; do echo -n ; done
^C
# asdfasdfahwefuiawhefouiaweh
sh in malloc(): error: recursive call.
Abort trap (core dumped)

[malloc_options="AX"]

Martin Cracaeur was the last person to touch the sh signal handling,
but I'm not sure if he touched anything unrelated to trap.c.

The signal handlers (onsig() and onint()) look pretty benign.  I can
reproduce it both with and without rootshell.  [See the patch at the
end of this message, though].


> By the way, I can't reproduce the problem if I compile with -DDEBUG=2.

Try harder.  :-)  It reproduces for me when compiled with -DDEBUG=2.


If I apply the following patch, I cannot reproduce the problem.

Perhaps this is enough to give someone who knows more about the sh
sources than me a quicker start on the problem.  [I assume it's not
the correct fix, although for all I know, it could be...  :-]

--- ~eval.c	Mon Aug 30 12:54:40 1999
+++ eval.c	Mon Aug 30 12:57:32 1999
@@ -289,7 +289,9 @@
 	loopnest++;
 	status = 0;
 	for (;;) {
+		INTOFF;
 		evaltree(n->nbinary.ch1, EV_TESTED);
+		INTON;
 		if (evalskip) {
 skipping:	  if (evalskip == SKIPCONT && --skipcount <= 0) {
 				evalskip = 0;
@@ -306,7 +308,9 @@
 			if (exitstatus == 0)
 				break;
 		}
+		INTOFF;
 		evaltree(n->nbinary.ch2, 0);
+		INTON;
 		status = exitstatus;
 		if (evalskip)
 			goto skipping;


-- 
This is my .signature which gets appended to the end of my messages.
Comment 3 Mike Barcroft freebsd_committer freebsd_triage 2001-07-21 01:36:48 UTC
State Changed
From-To: open->feedback


Does this problem still occur in newer versions of FreeBSD, 
such as 4.3-RELEASE?
Comment 4 Peter Avalos 2001-08-12 06:38:28 UTC
It still happens on my 4.4-PRERELEASE system. Source is from Aug. 11, 2001.

--Pete
Comment 5 Sheldon Hearn freebsd_committer freebsd_triage 2002-01-18 16:14:39 UTC
State Changed
From-To: feedback->closed

Automatic feedback timeout.  If additional feedback that warrants 
the re-opening of this PR is available but not included in the 
audit trail, please include the feedback in a reply to this message 
(preserving the Subject line) and ask that the PR be re-opened.