[comp.unix.wizards] signal handling,c-shell,hp840

eric@eddie.MIT.EDU (Eric Van Tassell) (12/13/87)

Ok, c-shell/bsd-wizards I give up.

suppose you have a binary foo who does a signal(SIGINT,mysighndlr) and the
following script.

foo.csh:
foo

in other words foo.csh merely calls foo.  Why does the parent c-shell catch
the ^C and terminate foo instead of letting mysighndlr handle it? How do I
enable my application to handle the signal? Please email. Oh yeah the system
involved is an HP9000/840 running HP-UX.


	Thanks in advance!

					eric@eddie.mit.edu

stroyan@hpfcdc.HP.COM (Mike Stroyan) (12/15/87)

An interactive csh will not exit when it receives a SIGINT signal, since
it is assumed that the SIGINT was intended for a child job.  A csh which
is excuting a shell script like foo.csh does exit, assuming that the
user intended to stop the shell script.  You can tell the foo.csh csh
to ignore SIGINT signals by putting "onintr -" into foo.csh.  You can
also tell csh to jump to a label by putting "onintr <label>" in foo.csh.

The child, foo, is not actually terminated if foo.csh exits.  It catches
the SIGINT signal and continues to run in the background, but does not
see further break or intr characters from the keyboard because it is in
another process group from the interactive shell.  You can still send it
SIGINT signals with the kill command.

Mike Stroyan, [hplabs!]hpfcla!stroyan

davel@hpcupt1.HP.COM (Dave Lennert) (12/17/87)

> The child, foo, is not actually terminated if foo.csh exits.  It catches
> the SIGINT signal and continues to run in the background, but does not
> see further break or intr characters from the keyboard because it is in
> another process group from the interactive shell.  You can still send it
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      true on the 840 because it supports job control

> SIGINT signals with the kill command.
> 
> Mike Stroyan, [hplabs!]hpfcla!stroyan

This is correct.  However, since the 840 supports job control, there is
an additional worry:  

When foo.csh exits (and foo continues to execute), the parent of foo.csh
continues.  If this parent is a csh, then it places itself into the
foreground and, hence, foo in the background.  If an orphaned background
process (foo, in this case) attempts to access the terminal, it will
stop and be killed by the kernel (SIGKILL).  This means that it will
silently terminate.  You can get around this, at least in the case of
write(), by either clearing the LTOSTOP bit (stty -tostop), which allows
write() for *all* background processes, or by setting SIGTTOU to SIG_IGN
in foo, which effects just foo.

-Dave Lennert   HP   ihnp4!hplabs!hpda!davel

allbery@ncoast.UUCP (Brandon Allbery) (12/18/87)

As quoted from <7649@eddie.MIT.EDU> by eric@eddie.MIT.EDU (Eric Van Tassell):
+---------------
| in other words foo.csh merely calls foo.  Why does the parent c-shell catch
| the ^C and terminate foo instead of letting mysighndlr handle it? How do I
| enable my application to handle the signal? Please email. Oh yeah the system
| involved is an HP9000/840 running HP-UX.
+---------------

I'm posting because it's a generic problem -- all shells have it, including
the V7 Bourne shell -- and because it puzzled me until I figured it out,
back when I was just starting out.

The reason for the behavior is that the Unix tty driver sends a SIGINT when
it receives your (bsd? t_intrc: c_cc[VINTR]) -- sends it to *all* your
processes, not just the "current" process.  (Having authored a "w" for System
V Release 2, I've had it quite forcefully driven home that Unix doesn't *have*
the notion of a "current" process.  This is a boon to process managing, but
a bust for status monitors.)  Since your "csh" is a process, it also receives
the SIGINT, which aborts the wait() done by csh and causes the csh to exit.
Your program ends up orphaned in the background, and probably dies due to
parental neglect.  ;-)

The way to prevent this is to add a statement to your csh script before it
runs "foo":  "onintr -", which tells csh to ignore SIGINT.  However, your
program must then trap SIGINT regarless of whether it is being ignored or
not -- a cardinal sin of signal handling, according to all my Unix programming
books.  For the Bourne shell, the proper statement is "trap '' 2"; actually,
the Bourne shell can do better with some fancy footwork: "trap 'trap : 2' 2"
will prevent /bin/sh from processing the signal without passing a SIG_IGN on
to the application.  (This is one reason why I prefer /bin/sh or ksh to csh.)

I personally think that shells should have a way of ignoring signals for the
duration of a command executing in the foreground.  However, I don't write
shells (well, not *those* shells...) so my opinion is worthless.
-- 
Brandon S. Allbery		      necntc!ncoast!allbery@harvard.harvard.edu
 {hoptoad,harvard!necntc,cbosgd,sun!mandrill!hal,uunet!hnsurg3}!ncoast!allbery
			Moderator of comp.sources.misc

allbery@ncoast.UUCP (Brandon Allbery) (12/18/87)

As quoted from <6812@ncoast.UUCP> by allbery@ncoast.UUCP (Brandon Allbery):
+---------------
| I personally think that shells should have a way of ignoring signals for the
| duration of a command executing in the foreground.  However, I don't write
| shells (well, not *those* shells...) so my opinion is worthless.
+---------------

Just to cover my *ss:  it should be obvious that the behavior described above
in fact exists... for interactive shells (sh and csh), NOT for scripts.
-- 
Brandon S. Allbery		      necntc!ncoast!allbery@harvard.harvard.edu
 {hoptoad,harvard!necntc,cbosgd,sun!mandrill!hal,uunet!hnsurg3}!ncoast!allbery
			Moderator of comp.sources.misc