how to suspend a process
Chris Torek
torek at elf.ee.lbl.gov
Mon Feb 18 20:51:17 AEST 1991
In article <121503 at uunet.UU.NET> rbj at uunet.UU.NET (Root Boy Jim) writes:
>In your handler, you send yourself a SIGSTOP, which you cannot catch.
>You could also unregister your handler, then send a SIGTSTP.
The second is `better' aesthetically.
Handling stops correctly is actually quite tricky. When you receive
a TSTP signal you may assume that all other processes in your process
group have also received one. You must therefore not send a second
TSTP to everyone (kill(0, SIGTSTP)) but rather only to yourself
(kill(getpid(), SIGTSTP)).
To make the stop `atomic' (i.e., to prevent users with itchy ^Z fingers
from stopping you while you are setting up to be stopped) you should
(a) be using the `Berkeley signal' mechanism (likely to be available,
if not the default, given that you have SIGTSTP in the first place);
(b) use code of the form:
stop_handler()
{
sigmask_t omask;
... do cleanup operations ...
/*
* SIGTSTP is currently blocked.
* To stop exactly once, send another TSTP in case
* none are pending. (If one is pending, the kill()
* will still leave exactly one pending.) Then
* atomically lower the mask and wait for the signal.
*
* Alternatively, we could use the sequence
* sigsetmask(omask & ~sigmask(SIGTSTP));
* sigsetmask(omask);
* which would let the signal in (thus stopping)
* then block the signal once we are resumed, but
* one call to sigpause is more efficient.
*/
omask = sigblock(0);
(void) kill(getpid(), SIGTSTP);
(void) sigpause(omask & ~sigmask(SIGTSTP));
... do setup again ...
}
The equivalent sequence of POSIX signal calls is:
sigset_t none, tmp;
(void) sigemptyset(&none);
(void) sigprocmask(SIG_BLOCK, &none, &tmp);
(void) sigdelset(&tmp, SIGTSTP);
(void) sigsuspend(&tmp);
If the reason you are catching signals is that you modify a tty state
(e.g., use CBREAK/not-ICANON mode), you should be careful to pick up
the new state after the stop. A number of programs, including `vi',
assume that the state they got when the first started is still in
effect, and the sequence:
% stty erase ^h
% vi
:stop
% stty erase ^_
% fg
:q
%
leaves erase set to ^H rather than ^_.
--
In-Real-Life: Chris Torek, Lawrence Berkeley Lab EE div (+1 415 486 5427)
Berkeley, CA Domain: torek at ee.lbl.gov
More information about the Comp.unix.questions
mailing list