From cracauer@cons.org  Tue Dec 22 09:22:00 1998
Received: from cons.org (knight.cons.org [194.233.237.86])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id JAA19623
          for <FreeBSD-gnats-submit@freebsd.org>; Tue, 22 Dec 1998 09:21:59 -0800 (PST)
          (envelope-from cracauer@cons.org)
Received: (from cracauer@localhost) by cons.org (8.8.8/8.7.3) id SAA05503; Tue, 22 Dec 1998 18:21:49 +0100 (CET)
Message-Id: <199812221721.SAA05503@cons.org>
Date: Tue, 22 Dec 1998 18:21:49 +0100 (CET)
From: cracauer@cons.org
Reply-To: cracauer@cons.org
To: FreeBSD-gnats-submit@freebsd.org
Subject: interactive /bin/sh should break loops on signals to childs
X-Send-Pr-Version: 3.2

>Number:         9173
>Category:       bin
>Synopsis:       Interactive /bin/sh loops should break when childs exits with signal status.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    cracauer
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Dec 22 09:30:01 PST 1998
>Closed-Date:    Sat Apr 3 14:56:23 MEST 1999
>Last-Modified:  Sat Apr  3 14:57:04 MEST 1999
>Originator:     Martin Cracauer
>Release:        FreeBSD 2.2.6-STABLE i386
>Organization:
>Environment:

All FreeBSD /bin/sh's after and before signal fixes from 1998.

>Description:

while : ; do
	sleep 2
done

Suppose the child (sleep) is killed by a signal (i.e. SIGINT,
SIGQUIT).

In a script (a non-interactivr shell) the shell executing the script
exits itself with signal status if a child returns with
WIFSIGNALED(status). 

In an interactive shell, you can't exit. But - and that is what
FreeBSD's sh does not - it should break the loop.

>How-To-Repeat:

In an interactive sh, type the following lines and try to break it by
some signal (SIGINT, SIGQUIT, whatever). The child (sleep) will
exit, but the loop will not end and hence a new sleep is spawned.

while : ; do
	sleep 2
done


>Fix:
	
If sh is running interactivly, it should remember the entry to a
loop. Only the outermost loop entry must be recognized, since you want
to break the outermost.

If a child dies with WIFSIGNALED(status), it should immedeatly break
all loops it is in.

You can't do this with setjmp/longjmp, since you want variable values
that were changed in the loop to persist.

The right approch is probably to change all calls to
  someloop() {
	status = waitforjob(jp);
	blabla();
  }

to
  someloop() {
	status = waitforjob(jp);
	if (is_interactive && WIFSIGNALED(status))
		break;
	blabla();
  }

The tricky part is to do this only for those places that actually are
parts of shell loops, otherwise you can easily shoot the user's login
shell :-] And don't forget to cleanup after yourself.

I'll give it a shot over holidyes, this PR is to document the
problem. 

Martin
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->cracauer 
Responsible-Changed-By: cracauer 
Responsible-Changed-When: Tue Dec 22 18:33:53 MET 1998 
Responsible-Changed-Why:  
I'm working on it. 
State-Changed-From-To: open->analyzed 
State-Changed-By: cracauer 
State-Changed-When: Tue Dec 22 18:35:05 MET 1998 
State-Changed-Why:  
As I think over it, it *is* analyzed 
State-Changed-From-To: analyzed->closed 
State-Changed-By: cracauer 
State-Changed-When: Sat Apr 3 14:56:23 MEST 1999 
State-Changed-Why:  
Fixed in 4.0-current from today. Will be fixed in 3.x in a few 
days. Releases 3.2 and 4.0 should have this change. 
>Unformatted:
