diff --git a/configure b/configure index 3945af07ab1..1d7b575433c 100755 --- a/configure +++ b/configure @@ -5930,87 +5930,13 @@ EOF fi -echo $ac_n "checking "for working sigaltstack"""... $ac_c" 1>&6 -echo "configure:5935: checking "for working sigaltstack"" >&5 -if eval "test \"`echo '$''{'ac_cv_c_working_sigaltstack'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_c_working_sigaltstack="no" - -else - cat > conftest.$ac_ext < - #include /* ? bad magic without end */ - #include - #include - #ifdef HAVE_SYS_PARAM_H - # include - #endif - #ifdef HAVE_SYSCALL_H - # include - #else - # ifdef HAVE_SYS_SYSCALL_H - # include - # endif - #endif - - unsigned char *xaltstack; - - int - main(int argc,char **argv) { - struct sigaltstack ss; - - xaltstack = malloc(16384); - ss.ss_sp = xaltstack; - ss.ss_size = 16384; - ss.ss_flags = 0; - if (sigaltstack(&ss, NULL) < 0) { - /* this catches the glibc case */ - perror("sigaltstack"); - return (1); /* aka exit(1) aka fail */ - } - /* assume it works. */ - return 0; /* OK */ - } - -EOF -if { (eval echo configure:5982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null -then - ac_cv_c_working_sigaltstack="yes" -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -fr conftest* - ac_cv_c_working_sigaltstack="no" -fi -rm -fr conftest* -fi - -fi - -echo "$ac_t""$ac_cv_c_working_sigaltstack" 1>&6 - -if test "$ac_cv_c_working_sigaltstack" = "yes" -then - cat >> confdefs.h <<\EOF -#define HAVE_WORKING_SIGALTSTACK 1 -EOF - -fi - - - echo $ac_n "checking "for msg_accrights in struct msghdr"""... $ac_c" 1>&6 -echo "configure:6009: checking "for msg_accrights in struct msghdr"" >&5 +echo "configure:5935: checking "for msg_accrights in struct msghdr"" >&5 if eval "test \"`echo '$''{'ac_cv_c_msg_accrights'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6018,7 +5944,7 @@ int main() { struct msghdr hdr; hdr.msg_accrights=0 ; return 0; } EOF -if { (eval echo configure:6022: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5948: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_msg_accrights="yes" else @@ -6041,12 +5967,12 @@ fi echo $ac_n "checking "for sun_len in struct sockaddr_un"""... $ac_c" 1>&6 -echo "configure:6045: checking "for sun_len in struct sockaddr_un"" >&5 +echo "configure:5971: checking "for sun_len in struct sockaddr_un"" >&5 if eval "test \"`echo '$''{'ac_cv_c_sun_len'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -6055,7 +5981,7 @@ int main() { static struct sockaddr_un addr; addr.sun_len = 1 ; return 0; } EOF -if { (eval echo configure:6059: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:5985: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_sun_len="yes" else @@ -6078,12 +6004,12 @@ fi echo $ac_n "checking "whether we need to define __i386__"""... $ac_c" 1>&6 -echo "configure:6082: checking "whether we need to define __i386__"" >&5 +echo "configure:6008: checking "whether we need to define __i386__"" >&5 if eval "test \"`echo '$''{'ac_cv_cpp_def_i386'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < - #include /* ? bad magic without end */ - #include - #include - #ifdef HAVE_SYS_PARAM_H - # include - #endif - #ifdef HAVE_SYSCALL_H - # include - #else - # ifdef HAVE_SYS_SYSCALL_H - # include - # endif - #endif - - unsigned char *xaltstack; - - int - main(int argc,char **argv) { - struct sigaltstack ss; - - xaltstack = malloc(16384); - ss.ss_sp = xaltstack; - ss.ss_size = 16384; - ss.ss_flags = 0; - if (sigaltstack(&ss, NULL) < 0) { - /* this catches the glibc case */ - perror("sigaltstack"); - return (1); /* aka exit(1) aka fail */ - } - /* assume it works. */ - return 0; /* OK */ - } - ], - ac_cv_c_working_sigaltstack="yes", - ac_cv_c_working_sigaltstack="no", - ac_cv_c_working_sigaltstack="no" -)) - -if test "$ac_cv_c_working_sigaltstack" = "yes" -then - AC_DEFINE(HAVE_WORKING_SIGALTSTACK) -fi - - dnl *** check for file descriptor passing with msg_accrights AC_CACHE_CHECK("for msg_accrights in struct msghdr", ac_cv_c_msg_accrights, diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index e964f8f00bb..24818b8773e 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -62,13 +62,12 @@ typedef struct #define HANDLER_CONTEXT (&__context) /* this is the sigaction structure from the Linux 2.1.20 kernel. */ -#undef sa_handler struct kernel_sigaction { - void (*sa_handler)(); - unsigned long sa_mask; - unsigned long sa_flags; - void *sa_restorer; + void (*ksa_handler)(); + unsigned long ksa_mask; + unsigned long ksa_flags; + void *ksa_restorer; }; /* Similar to the sigaction function in libc, except it leaves alone the @@ -87,6 +86,24 @@ static inline int wine_sigaction( int sig, struct kernel_sigaction *new, return -1; } +#ifdef HAVE_SIGALTSTACK +/* direct syscall for sigaltstack to work around glibc 2.0 brain-damage */ +static inline int wine_sigaltstack( const struct sigaltstack *new, + struct sigaltstack *old ) +{ + int ret; + __asm__ __volatile__( "pushl %%ebx\n\t" + "movl %2,%%ebx\n\t" + "int $0x80\n\t" + "popl %%ebx" + : "=a" (ret) + : "0" (SYS_sigaltstack), "r" (new), "c" (old) ); + if (ret >= 0) return 0; + errno = -ret; + return -1; +} +#endif + #endif /* linux */ #ifdef BSDI @@ -660,32 +677,37 @@ static HANDLER_DEF(int_handler) * * Set a signal handler */ -static int set_handler( int sig, void (*func)() ) +static int set_handler( int sig, int have_sigaltstack, void (*func)() ) { -#ifdef linux - struct kernel_sigaction sig_act; - sig_act.sa_handler = func; - sig_act.sa_flags = SA_RESTART | SA_NOMASK; - sig_act.sa_mask = 0; - /* point to the top of the stack */ - sig_act.sa_restorer = (char *)NtCurrentTeb()->signal_stack + SIGNAL_STACK_SIZE; - return wine_sigaction( sig, &sig_act, NULL ); -#else /* linux */ struct sigaction sig_act; + +#ifdef linux + if (!have_sigaltstack && NtCurrentTeb()->signal_stack) + { + struct kernel_sigaction sig_act; + sig_act.ksa_handler = func; + sig_act.ksa_flags = SA_RESTART | SA_NOMASK; + sig_act.ksa_mask = 0; + /* point to the top of the stack */ + sig_act.ksa_restorer = (char *)NtCurrentTeb()->signal_stack + SIGNAL_STACK_SIZE; + return wine_sigaction( sig, &sig_act, NULL ); + } +#endif /* linux */ sig_act.sa_handler = func; sigemptyset( &sig_act.sa_mask ); -# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) - sig_act.sa_flags = SA_ONSTACK; -# elif defined (__svr4__) || defined(_SCO_DS) - sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART; -# elif defined(__EMX__) - sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */ -# else +#ifdef linux + sig_act.sa_flags = SA_RESTART | SA_NOMASK; +#elif defined (__svr4__) || defined(_SCO_DS) + sig_act.sa_flags = SA_SIGINFO | SA_RESTART; +#else sig_act.sa_flags = 0; -# endif +#endif + +#ifdef SA_ONSTACK + if (have_sigaltstack) sig_act.sa_flags |= SA_ONSTACK; +#endif return sigaction( sig, &sig_act, NULL ); -#endif /* linux */ } @@ -694,17 +716,21 @@ static int set_handler( int sig, void (*func)() ) */ BOOL SIGNAL_Init(void) { -#ifdef HAVE_WORKING_SIGALTSTACK + int have_sigaltstack = 0; + +#ifdef HAVE_SIGALTSTACK struct sigaltstack ss; if ((ss.ss_sp = NtCurrentTeb()->signal_stack)) { ss.ss_size = SIGNAL_STACK_SIZE; ss.ss_flags = 0; - if (sigaltstack(&ss, NULL) < 0) - { - perror("sigaltstack"); - /* fall through on error and try it differently */ - } + if (!sigaltstack(&ss, NULL)) have_sigaltstack = 1; +#ifdef linux + /* sigaltstack may fail because the kernel is too old, or + because glibc is brain-dead. In the latter case a + direct system call should succeed. */ + else if (!wine_sigaltstack(&ss, NULL)) have_sigaltstack = 1; +#endif /* linux */ } #endif /* HAVE_SIGALTSTACK */ @@ -713,15 +739,15 @@ BOOL SIGNAL_Init(void) /* automatic child reaping to avoid zombies */ signal( SIGCHLD, SIG_IGN ); - if (set_handler( SIGINT, (void (*)())int_handler ) == -1) goto error; - if (set_handler( SIGFPE, (void (*)())fpe_handler ) == -1) goto error; - if (set_handler( SIGSEGV, (void (*)())segv_handler ) == -1) goto error; - if (set_handler( SIGILL, (void (*)())segv_handler ) == -1) goto error; + if (set_handler( SIGINT, have_sigaltstack, (void (*)())int_handler ) == -1) goto error; + if (set_handler( SIGFPE, have_sigaltstack, (void (*)())fpe_handler ) == -1) goto error; + if (set_handler( SIGSEGV, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; + if (set_handler( SIGILL, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; #ifdef SIGBUS - if (set_handler( SIGBUS, (void (*)())segv_handler ) == -1) goto error; + if (set_handler( SIGBUS, have_sigaltstack, (void (*)())segv_handler ) == -1) goto error; #endif #ifdef SIGTRAP - if (set_handler( SIGTRAP, (void (*)())trap_handler ) == -1) goto error; + if (set_handler( SIGTRAP, have_sigaltstack, (void (*)())trap_handler ) == -1) goto error; #endif return TRUE; diff --git a/include/acconfig.h b/include/acconfig.h index 87ba6c6940c..8f1f449b51a 100644 --- a/include/acconfig.h +++ b/include/acconfig.h @@ -66,9 +66,6 @@ /* Define if the struct statfs has the member bfree */ #undef STATFS_HAS_BFREE -/* Define if we have a working sigaltstack */ -#undef HAVE_WORKING_SIGALTSTACK - /* Define if the struct statfs is defined by */ #undef STATFS_DEFINED_BY_SYS_VFS diff --git a/include/config.h.in b/include/config.h.in index d94db3cd717..7a2a5cb045a 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -107,9 +107,6 @@ /* Define if the struct statfs has the member bfree */ #undef STATFS_HAS_BFREE -/* Define if we have a working sigaltstack */ -#undef HAVE_WORKING_SIGALTSTACK - /* Define if the struct statfs is defined by */ #undef STATFS_DEFINED_BY_SYS_VFS