[Search for users]
[Overall Top Noters]
[List of all Conferences]
[Download this site]
Title: | DIGITAL UNIX (FORMERLY KNOWN AS DEC OSF/1) |
Notice: | Welcome to the Digital UNIX Conference |
Moderator: | SMURF::DENHAM |
|
Created: | Thu Mar 16 1995 |
Last Modified: | Fri Jun 06 1997 |
Last Successful Update: | Fri Jun 06 1997 |
Number of topics: | 10068 |
Total number of notes: | 35879 |
8726.0. "signals & kill system call problem" by TAEC::GARNERO () Wed Feb 05 1997 11:56
Hello,
I am experiencing a problem with the kill system call on DU V4.0B.
I have written a program which is doing the following:
. Set a signal handler in charge to process the SIGSEGV signal.
This signal handler perform a kill(getpid(),SIGTERM) call.
. A service thread is in charge to "sigwait" on SIGTERM signal.
SIGTERM is blocked from delivery.
. A "work" thread perform an illegal instruction resulting in
raising the SIGSEGV synchronous signal.
SIGTERM is blocked from delivery.
When I start this program I get:
mouete.vbe.dec.com> signal_test
Terminated
-> the service thread is not activated
Then, when I replace the kill system call by a pthread_kill call specifying the
service
thread (doing sigwait), I get a program working perfectly:
mouete.vbe.dec.com> signal_test
service_thread : signal delivered : 15
I know that SIGTERM is not blocked from delivery in the main thread but I have
read (note 3318.8) that if 1 thread is doing a sigwait on a signal, the signal
will be delivered to this thread even if many other threads have this signal not
blocked.
The program is compiled:
mouete.vbe.dec.com> cc -c -D_REENTRANT signal_test.c
mouete.vbe.dec.com> cc -o signal_test signal_test.o -lpthread -lc
Could someone tell me what is going ?
Thank you in advance.
/Pierre
Following is the source code of the program:
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
pthread_t service;
pthread_t work;
void *
service_thread(void *arg)
{
int sig;
sigset_t sigset ;
int ret;
if ( sigemptyset ( &sigset ) != 0 ) { perror("pb sigemptyset"); exit(0); }
if ( sigaddset ( &sigset , SIGTERM ) != 0 ) { perror("pb sigaddset"); exit(0);
}
if ( ( ret = pthread_sigmask ( SIG_SETMASK , &sigset , NULL ) ) != 0) {
printf("pb pthread_sigmask: %d\n",ret); exit(0); }
if ( ( ret = sigwait(&sigset,&sig ) ) != 0) { printf("pb sigwait: %d\n",ret);
exit(0); }
printf("service_thread : signal delivered : %d\n",sig);
}
void *
work_thread(void *arg)
{
sigset_t sigset ;
int ret;
char *c;
if ( sigemptyset ( &sigset ) != 0 ) { perror("pb sigemptyset"); exit(0); }
if ( sigaddset ( &sigset , SIGTERM ) != 0 ) { perror("pb sigaddset"); exit(0);
}
if ( ( ret = pthread_sigmask ( SIG_SETMASK , &sigset , NULL ) ) != 0) {
printf("pb pthread_sigmask: %d\n",ret); exit(0); }
sleep(1);
*c = 'a' ;
sleep(1000);
}
void signal_handler(int sig)
{
if ( kill(getpid(),SIGTERM) != 0) { perror("pb kill"); }
/* pthread_kill(service,SIGTERM); */
}
main()
{
struct sigaction action;
int ret ;
action.sa_handler = signal_handler ;
action.sa_mask = 0 ;
action.sa_flags = 0 ;
if ( sigaction(SIGSEGV,&action,NULL) != 0 ) { perror("pb sigaction\n");
exit(0); }
if ( ( ret = pthread_create(&service,NULL,service_thread,NULL) ) != 0 ) {
printf("pb pthread_create : %d\n",ret); exit(0); }
if ( ( ret = pthread_create(&work,NULL,work_thread,NULL) ) != 0 ) { printf("pb
pthread_create : %d\n",ret); exit(0); }
sleep(1000);
}
T.R | Title | User | Personal Name | Date | Lines |
---|
8726.1 | | SMURF::DENHAM | Digital UNIX Kernel | Wed Feb 05 1997 14:32 | 12 |
| Well, first off, don't depend on implementation quirks. To use
sigwait reliably, you simply need to make sure that the sigwaited
signals are blocked in all other threads. Or that you have handler
in place that doesn't the right thing when you sigwait thread
doesn't happen to be in sigwait.
Blocking the signal in main() so that all the threads inherit
SIGTERM blocked causes the expected behavior and is the right
way to code it.
I am curious about the blip in the sigwait behavior, but it's
not a bug.
|
8726.2 | | SMURF::DENHAM | Digital UNIX Kernel | Wed Feb 05 1997 17:31 | 20 |
| Found your problem.
The thread that raises the SEGV on itself then signals does
nothing to prevent itself from returning to the line of code
that causes the seg fault. Thus, before the sigwait thread
ever returns from the kernel, it may well run again, get another
SEGV and raise SIGTERM yet again. Because the sigwait thread
is no longer is sigwait, BOOM, the main thread gets the signal.
This is exactly the reason you want the signal blocked in those
other threads.
If you add a sleep(1) in the signal handler for SEGV you'll
see that the "problem" goes away. A long jump out of the handler
to a safe PC could also work. Even with the signal blocked in
the main thread, you don't want this worker thread in this
potentially infinite SEGV loop.
Hope that all makes some sense.
|
8726.3 | thanks for your replies | TAEC::GARNERO | | Thu Feb 06 1997 02:24 | 0
|