[Mono-list] catching stack overflow signals
Daniel Stodden
stodden@in.tum.de
21 Jun 2002 04:04:41 +0200
--=-xUP2407B3E4x0NcwP0wM
Content-Type: text/plain
Content-Transfer-Encoding: 7bit
On Wed, 2002-06-19 at 17:42, Dietmar Maurer wrote:
> Hi all,
hi.
> On workaround is to use a stack allocated memory for sigaltstack, for
> example we can define a local variable:
>
> char alttack [8192] __attribute__ (( aligned (32) ));
>
> That way we solve the above problem, but i am quite sure that this will
> confuse pthread somehow, because its thread detection always points to
> the same thread in signal handler.
indeed it would.
> So maybe someone knows a better solution?
i don't see any alternative to altstack.
win32 seems to handle the overflow problem more elegantly by releasing
the page protection bit on the guard. exception handlers can then try to
recover from within the guard region. [1]
sigaltstack however seems at least to be smart enough _not_ to share
alternates between threads.
i haven't looked this up in the kernel yet, though.
seems installing an altstack on on a per thread start basis fixes the
problem. see the attached update.
regards,
dns
[1]http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaskdr/html/drgui49.asp
--
___________________________________________________________________________
mailto:stodden@in.tum.de
--=-xUP2407B3E4x0NcwP0wM
Content-Disposition: attachment; filename=sigtest2.c
Content-Transfer-Encoding: quoted-printable
Content-Type: text/x-c; name=sigtest2.c; charset=ISO-8859-1
#include <stdlib.h>
#include <sys/signal.h>
#define __USE_GNU
#include <pthread.h>
#include <setjmp.h>
void
stack_overflow( int count )
{
char buf[2 * pthread_self()];
printf( "thread=3D%d count=3D%d, stack=3D%p\n",=20
pthread_self(), count, buf );
if ( count % 10 =3D=3D 0 ) {
printf( "-- yield --\n" );
pthread_yield();
}
stack_overflow( count + 1);
}
#ifdef __i386__
#define _STACK_GROWS_DOWN 1
#else
#error "intel outside, huh?"
#endif
void sa_segv_action( int sig, siginfo_t *info, void *arg )
{
int ss_sp;
pthread_t self =3D pthread_self();
pthread_attr_t attr;
void *staddr;
size_t stsize;
void *gdstart, *gdend;
size_t gdsize;
int ovf =3D 0;
printf( "caught signal: thread=3D%d, ss_sp=3D%p\n",=20
self, &ss_sp );
printf( "fault at: %p\n", info->si_addr );
// FIXME: won't work for the parent
pthread_getattr_np( self, &attr );
pthread_attr_getstack( &attr, &staddr, &stsize );
pthread_attr_getguardsize( &attr, &gdsize );
printf( "stack addr: %p\n", staddr );
printf( "guard size: %p\n", gdsize );
=09
#if _STACK_GROWS_DOWN
gdstart =3D staddr - gdsize;
gdend =3D staddr;
#elif _STACK_GROWS_UP
ovf =3D /* FIXME */;
#elif NEED_SEPARATE_REGISTER_STACK
ovf =3D /* FIXME */;
#endif
if ( gdstart <=3D info->si_addr && info->si_addr < gdend )
printf( "stack overflow, indeed\n" );
else
printf( "ordinary gpf\n" );
printf( "-- die --\n" );
pthread_exit( NULL );
}
#define STACKSIZE SIGSTKSZ
void *
thread_start( void *arg )
{
struct sigaltstack sa;
char altstack[SIGSTKSZ];
sa.ss_sp =3D altstack;
sa.ss_size =3D STACKSIZE;
sa.ss_flags =3D SS_ONSTACK;
sigaltstack( &sa, NULL );
printf( "thread starts: self=3D%d, stack=3D%p\n", pthread_self(), altstack=
);
stack_overflow( 0 );
return NULL;
}
int
main( int argc, char **argv )
{
pthread_attr_t attr;
size_t guardsize;
pthread_t thread1, thread2;
struct sigaction act;
act.sa_sigaction =3D sa_segv_action;
act.sa_flags =3D SA_SIGINFO | SA_ONSTACK;
sigaction( SIGSEGV, &act, 0);
pthread_attr_getguardsize( &attr, &guardsize );
printf( "guardsize=3D%d\n", guardsize );
if ( pthread_create( &thread1, NULL, thread_start, NULL ) ) {
printf( "could not create first thread\n" );
exit( 1 );
}
if ( pthread_create( &thread2, NULL, thread_start, NULL ) ) {
printf( "could not create second thread\n" );
exit( 1 );
}
pthread_join( thread1, NULL );
pthread_join( thread2, NULL );
return 0;
}
--=-xUP2407B3E4x0NcwP0wM--