Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 22 Dec 1998 18:21:49 +0100 (CET)
From:      cracauer@cons.org
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   bin/9173: interactive /bin/sh should break loops on signals to childs
Message-ID:  <199812221721.SAA05503@cons.org>

next in thread | raw e-mail | index | archive | help


>Number:         9173
>Category:       bin
>Synopsis:       Interactive /bin/sh loops should break when childs exits with signal status.
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Dec 22 09:30:01 PST 1998
>Last-Modified:
>Originator:     Martin Cracauer
>Organization:
>Release:        FreeBSD 2.2.6-STABLE i386
>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
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199812221721.SAA05503>