T.R | Title | User | Personal Name | Date | Lines |
---|
9898.1 | Use sigaction(2) instead of old signal(2) | CECMOW::RAIKO | | Wed May 21 1997 05:49 | 0 |
9898.2 | Same result in sigaction( ) ! | NNTPD::"[email protected]" | Seok-Hwan, Lee | Wed May 21 1997 06:22 | 56 |
| I try to excute program using sigaction(), but I have
same result !
changed sample program is next following:#include <signal.h>
--------------------------------------------------
#include <signal.h>
struct sigaction sa;
void
sigh( int n )
{
int cpid;
sigaction(SIGCHLD, &sa, NULL);
printf( "----- sigh function called ---SIGH\n" );
cpid=wait( (int *)0 );
printf( "Wait func cpid = %d\n", cpid );
}
void
main()
{
int cpid=0;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SIGCHLD;
sa.sa_handler = sigh;
sigaction(SIGCHLD, &sa, NULL);
if( (cpid = fork()) == 0 )
{
printf("fork1 ok\n");
exit();
}
printf("1: cpid = %d \n", cpid);
if( (cpid = fork()) == 0 )
{
printf("fork2 ok\n");
exit();
}
printf("2: cpid = %d \n", cpid);
if( (cpid = fork()) == 0 )
{
printf("fork3 ok\n");
exit();
}
printf("3: cpid = %d \n", cpid);
sleep( 3 );
while( 1 )
{
printf( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" );
sleep( 2 );
}
}
[Posted by WWW Notes gateway]
|
9898.3 | | MSKRAT::ANKAN | Idle words waste time | Wed May 21 1997 11:16 | 16 |
| Well, just change your signal handler to something like:
void
sigh( int n )
{
int cpid;
sigaction(SIGCHLD, &sa, NULL);
printf( "----- sigh function called ---SIGH\n" );
while ((cpid=wait( (int *)0 )) > 0) {
printf( "Wait func cpid = %d\n", cpid );
}
}
...and you should be all set. More than one child death can be
pending for a single signal.
|
9898.4 | | SMURF::DENHAM | Digital UNIX Kernel | Wed May 21 1997 11:19 | 6 |
| That's the idea in the last reply. There's simply *no way* to
guarantee a signal for every child -- those signals don't queue
in the realtime fashion. Instead, you need to call waitpid or
wait3 or wait4 or waitid with the WNOHANG flag in a loop until
it returns failure. If you don't you the no-hang option, you
handler will indeed hang.
|
9898.5 | Be careful what you try to do in a signal handler | WTFN::SCALES | Despair is appropriate and inevitable. | Wed May 21 1997 12:16 | 9 |
| .3> Well, just change your signal handler to something like:
Yes, but... There's a small list of "signal-safe" functions -- those which
are safe for use in signal handlers -- and printf() is _not_ one of them...
See the signal(4) man page. The wait*() functions, however, -are-
signal-safe. :-)
Webb
|
9898.6 | | MSKRAT::ANKAN | Idle words waste time | Wed May 21 1997 14:32 | 14 |
| Nitty picky... all I need is pthread_cond_signal_int_np :-)
But, signal(4) sure raised a question; to quote:
"The signal-catching function can cause the process to resume in a different
context by calling the longjmp() subroutine. When the longjmp() subroutine
is called, the process leaves the signal stack, if it is currently on it,
and restores the process signal mask to the state when the corresponding
setjmp() call was made."
So, if a longjmp() out of the signal handler, could I call a pthread
routine, or even printf()?
|
9898.7 | I depends on how we implemented it... | WTFN::SCALES | Despair is appropriate and inevitable. | Wed May 21 1997 15:15 | 31 |
| .6> if a longjmp() out of the signal handler, could I call a pthread routine, or
.6> even printf()?
The answer is supposed to be "yes": once you've completed the jump, you are no
longer in the context of a signal handler, and so you are not bound by the
restrictions in signal(4).
However, as I sit here, I can't say with any confidence that that is indeed the
case. I think it all depends on how longjmp() is implemented, and how the
non-signal-safe routines (such as printf()) are constructed. That is, if
longjmp() were implemented such that it unwound the stack, frame by frame
(instead of arbitrarily rewriting the register set), such that any interested
routine could declare an "unwind handler" which would allow it to clean up in
the event of a longjmp(), then there would be the possibility of making things
work after jumping out of a signal handler.
The problem is that the signal could be delivered at a moment when the state in
some routine is inconsistent from an outside perspective. For example, suppose
the signal interrupts printf() after it's filled the output buffer but before
it's flushed it (or any of several equivalent places): calling printf() from
the signal handler could result in corruptions of either memory or the output
stream (i.e., output would be lost), and doing the longjmp() first wouldn't
change anything, _unless_ printf() could tell that the jump is occurring. The
situation gets even worse when you introduce threads and mutexes...
So, yeah, it's supposed to work, but I've grave doubts as to whether it actually
does. Thus, it's best to avoid doing anything more than you have to in a signal
handler, and only use setjmp() and longjmp() where you absolutely have to!
Webb
|
9898.8 | | SMURF::DENHAM | Digital UNIX Kernel | Wed May 21 1997 18:10 | 8 |
| Big dittos for Webb's reponse. There is indeed no unwinding done
for a longjmp -- just Boom, you're back at the saved context.
If you're in a threaded environment, using structure exceptions
is a much better model. The exception code *does* do sane unwinding
before it calls the kernel equivalent of longjmp, sigreturn.
So, you would be able to back out of mutexs taken before the
signal was generated....
|
9898.9 | | DCETHD::BUTENHOF | Dave Butenhof, DECthreads | Thu May 22 1997 07:21 | 36 |
| > If you're in a threaded environment, using structure exceptions
> is a much better model. The exception code *does* do sane unwinding
> before it calls the kernel equivalent of longjmp, sigreturn.
> So, you would be able to back out of mutexs taken before the
> signal was generated....
Of course beware that libc does NOT have exception handlers, and will NOT
restore data invariants or unlock mutexes when "unwound". So an async signal
action invoked while in, for example, printf, that is unwound past the printf
call by raising an exception, will leave the file stream inconsistent and,
very likely, the mutex locked.
The libc routines are thread-safe, but they are not async signal safe.
Technically, when you call longjmp (or siglongjmp) from a signal action you
are not actually "returning" from the signal action routine. Although one can
infer from the too-specific language ("if they are called from a
signal-catching function") that it's OK to call non-async-safe functions
after a longjmp() to "another function", the standard does not actually deal
with this case. Making such an inference is very dangerous, because I very
much doubt that any implementation of UNIX, with or without threads, will
meet the expectation. If you asynchronously interrupt a stdio function in the
process of modifying the file stream state, and longjmp somewhere else, you
WILL leave the stream in an inconsistent state. Period. The result may or may
not disrupt the process at some later time, depending on how serious the
inconsistency is. (Without threads, you're not likely to do much more than
overwrite some characters in the output buffer -- but there's no
architectural guarantee of that!)
(Hmmm... the ANSI C definition of longjmp() prohibits an implementation that
"cleans up" state from the intermediate frames... it requires specifically
that "All accessible objects have values as of the time longjmp was
called...". I hate it when standards paint themselves into a corner where the
functions cannot be made to work correctly!)
/dave
|