Speaking of sigaltstack...

Tom Gall tom_gall@vnet.ibm.com
Sun Feb 9 05:18:00 GMT 2003


Greetings All,

   Been troubleshooting an interesting bug with linuxthreads and 
sigaltstack. The bug is in glibc 2.2.5 for all architectures (and I 
wouldn't doubt in later versions of glibc)

   Anyway given the following little test program:

#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>

void xregister( void );

typedef unsigned long ss_stackframeaccess_t;

static __inline__ ss_stackframeaccess_t ss_readframeanchor( void )
{
           ss_stackframeaccess_t r;
             __asm__("movl %%ebp,%0"
                                       : "=r" (r));
               return r;
} /* End of ss_readframeanchor */

static void ss_signalhandler( int signo, siginfo_t *info, void *uc )
{
         int pid;

         pid = getpid();
         printf ("signal handler 1 pid was %d ebp=%lx\n", 
pid,ss_readframeanchor());
         sleep(2);
         exit(1);
}

static void *thread( void *arg )
{
         printf("thread has pid %d\n",getpid());

         while ( 1 ) { sleep(1); }
         return NULL;
}

void xregister( void )
{
         stack_t altstack;
         char *stack;
         int rc;
         struct sigaction sa;

         stack = malloc(65536);
         altstack.ss_sp    = stack;
         altstack.ss_flags = SS_ONSTACK;
         altstack.ss_size  = 65536;
         rc = sigaltstack( &altstack, NULL );
         if (rc != 0) {
                 perror("sigaltstack");
                 exit(1);
         }
         printf("pid %d stack %p to %p\n",getpid(),stack,stack+65536);

         sa.sa_sigaction = ss_signalhandler;
         sigemptyset( &sa.sa_mask );
         sa.sa_flags = SA_SIGINFO | SA_ONSTACK;

         sigaction( SIGHUP,  &sa, NULL );
         sigaction( SIGINT,  &sa, NULL );
         sigaction( SIGTERM, &sa, NULL );
         sigaction( SIGFPE,  &sa, NULL );
         sigaction( SIGSEGV, &sa, NULL );
         sigaction( SIGILL,  &sa, NULL );
         sigaction( SIGBUS,  &sa, NULL );

}

int main( void )
{
         pthread_t thd;

         pthread_create( &thd, NULL, thread, NULL );
         pthread_create( &thd, NULL, thread, NULL );
         pthread_create( &thd, NULL, thread, NULL );
         pthread_create( &thd, NULL, thread, NULL );
         xregister();

         while (1) { sleep(1);
         }
         return 0;
}

   Compile. Run. kill the parent pid.  ps and You'll see the manager 
thread is defunct.

   It would appear that in linuxthreads when the pthread signal handler 
wrapper gets control in the manager thread, and calls thread_self, it 
gets the alternate stack and BOOM, that's all she wrote.

   So the question of the moment is how to fix this beast.  Should 
thread_self just realize it's on an alt stack and ?  If so, any 
suggestions as best to the approach? This feels like one of those areas 
where thread local storage would come in handy.

   Interestly enough RedHat 7.3's glibc appears to do just that. But 
later versions fail. SuSE as well.

   I'm not particularly familiar with the internal workings of 
linuxthreads. Any comments, and suggestions would be very valuable.

   Past postings appear to have mentioned the problem but never saw a 
resolution. Thanks in advance.

   Regards,

   Tom



More information about the Libc-alpha mailing list