Commit 0045def7 authored by Alexandre Julliard's avatar Alexandre Julliard

Fixed signal stack handling on Linux when sigaltstack is available.

Added a direct sigaltstack syscall to work-around the glibc bug.
parent 51f6aeb4
......@@ -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 <<EOF
#line 5944 "configure"
#include "confdefs.h"
#include <stdio.h>
#include <time.h> /* <sys/time.h> ? bad magic without end */
#include <sys/types.h>
#include <sys/signal.h>
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
# ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
# 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 <<EOF
#line 6014 "configure"
#line 5940 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
......@@ -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 <<EOF
#line 6050 "configure"
#line 5976 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
......@@ -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 <<EOF
#line 6087 "configure"
#line 6013 "configure"
#include "confdefs.h"
#if (defined(i386) || defined(__i386)) && !defined(__i386__)
yes
......
......@@ -867,57 +867,6 @@ then
AC_DEFINE(STATFS_HAS_BAVAIL)
fi
dnl *** check for working sigaltstack
dnl glibc 2.0x defines it, but it always fails... so it is useless for us.
AC_CACHE_CHECK("for working sigaltstack",
ac_cv_c_working_sigaltstack,
AC_TRY_RUN([
#include <stdio.h>
#include <time.h> /* <sys/time.h> ? bad magic without end */
#include <sys/types.h>
#include <sys/signal.h>
#ifdef HAVE_SYS_PARAM_H
# include <sys/param.h>
#endif
#ifdef HAVE_SYSCALL_H
# include <syscall.h>
#else
# ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
# 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,
......
......@@ -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;
......
......@@ -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 <sys/vfs.h> */
#undef STATFS_DEFINED_BY_SYS_VFS
......
......@@ -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 <sys/vfs.h> */
#undef STATFS_DEFINED_BY_SYS_VFS
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment