Subject: Re: Sane exit from a program on receipt of a signal
To: None <tech-userlevel@NetBSD.org>
From: ITOH Yasufumi <itohy@NetBSD.org>
List: tech-userlevel
Date: 07/26/2007 15:07:14
Hm, before unusual SIGTSTP usages, we should discuss normal SIGTSTP usages.

The most normal way to suspend a foreground job (aka process group) is this.

 0. Send SIGTSTP to the process group, which do the default behavior.
    (such as kill(-pgid, SIGTSTP))

If the process group needs some work before suspension,
the most foreground process of the process group will
do one from following.

 1. Simulate tty SIGTSTP.  If the process wants to suspend, send SIGTSTP
    to its own process group.
    (such as kill(0, SIGTSTP))

 2. Trap SIGTSTP, do something, reset signal hander and resend SIGTSTP
    to itself.

A SIGTSTP usage other than above is just a corner case or an accident.

Since 1. is the most often the case that requires SIGTSTP handling,
we need kill(0, SIGTSTP) anyway.

The case 2. we can use either kill(getpid(), SIGTSTP) or kill(0, SIGTSTP).
I'd recommend kill(0, SIGTSTP) here since
 - we can share the same code with 1.,
 - code is simpler,
 - it behaves better (for users) in the corner cases.


OK, then, let's discuss the corner cases.

mouse@Rodents.Montreal.QC.CA writes:
> >>> As for SIGTSTP and other tty signals, the signal should be sent to
> >>> the process group rather than to just the current process.
> >> I disagree.
> > Take a look at curses(3) and other SIGTSTP-aware software.  You will
> > easily find kill(0, SIGTSTP).
> 
> So?  Just because other software is broken is no reason for us to write
> more broken software.  (I wasn't aware of this bug in curses; it really
> ought to be fixed.  Thanks for pointing it out.)

What is the benefit of ``fixing'' programs to be less safe to users?

> > Stopping only one process of a process group will cause serious
> > problems with BSD job control and must be avoided.
> 
> Right.  So?  As I wrote, if it was generated from the tty, it's already
> been sent to the rest of the process group.  If it was generated with
> kill(), then either it's already been sent to the rest of the process
> group or it shouldn't be sent to the rest of the process group.

As you notice, it is not needed, but does no harm.  So this is OK.

> > BSD is carefully designed to allow kill(0, SIGTSTP) in the former
> > case.  Sending SIGTSTP to already stopped processes is ignored
> > happily.
> 
> Yes...if the process happens to be stopped at that point.  Which it may
> not be, for any of various reasons.

I admit it is a waste, but better than leaving terminal unusable when
the SIGTSTP is sent to this process specifically.  It is impossible
for the process to distinguish the cases.

> > In the latter case ["If it was sent to this process specifically"],
> > stopping one process of a process group may left the terminal in
> > unusable state, and stopping the process group is user's benefit.
> 
> That's as may be.  But it is not for us to make that decision; that is
> for the signal's sender to decide.  If the signal was sent to us and no
> other process, it is not for us to say that it should be rebroadcast to
> others; we should behave as much as possible like a process with no
> handling installed, which does *not* include re-sending the signal

You can use SIGSTOP (not SIGTSTP) for that purpose.
SIGSTOP works even on orphaned process groups.

Regards,
-- 
ITOH Yasufumi