Fixed signal stack handling on Linux when sigaltstack is available.
Added a direct sigaltstack syscall to work-around the glibc bug.
This commit is contained in:
parent
51f6aeb462
commit
0045def764
|
@ -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
|
||||
|
|
51
configure.in
51
configure.in
|
@ -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;
|
||||
#ifdef linux
|
||||
sig_act.sa_flags = SA_RESTART | SA_NOMASK;
|
||||
#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 */
|
||||
sig_act.sa_flags = SA_SIGINFO | SA_RESTART;
|
||||
#else
|
||||
sig_act.sa_flags = 0;
|
||||
#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
|
||||
|
||||
|
|
Loading…
Reference in New Issue