[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference turris::digital_unix

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.RTitleUserPersonal
Name
DateLines
8726.1SMURF::DENHAMDigital UNIX KernelWed Feb 05 1997 14:3212
    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.2SMURF::DENHAMDigital UNIX KernelWed Feb 05 1997 17:3120
    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.3thanks for your repliesTAEC::GARNEROThu Feb 06 1997 02:240