Trying to fix sigaltstack() problem reported by Debian users.
[wine/wine-kai.git] / loader / signal.c
blob1fdb019ed8268b24fb4b99b7e861a9ce258973f0
1 /*
2 * Wine signal handling
4 * Copyright 1995 Alexandre Julliard
5 */
7 #include "config.h"
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <signal.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <time.h>
16 #include <setjmp.h>
18 #include <sys/time.h>
19 #include <sys/timeb.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
23 #ifdef HAVE_SYS_PARAM_H
24 # include <sys/param.h>
25 #endif
26 #ifdef HAVE_SYSCALL_H
27 # include <syscall.h>
28 #else
29 # ifdef HAVE_SYS_SYSCALL_H
30 # include <sys/syscall.h>
31 # endif
32 #endif
34 #include "winsock.h"
35 #include "global.h"
36 #include "options.h"
37 #include "debugger.h"
38 #include "miscemu.h"
39 #include "dosexe.h"
40 #include "thread.h"
41 #include "debug.h"
43 void (*fnWINE_Debugger)(int,SIGCONTEXT*) = NULL;
44 void (*ctx_debug_call)(int sig,CONTEXT*ctx)=NULL;
45 BOOL (*fnINSTR_EmulateInstruction)(SIGCONTEXT*ctx)=NULL;
48 #ifdef __i386__
50 /* i386 specific faults */
51 static const char * const SIGNAL_traps[] =
53 "Division by zero exception", /* 0 */
54 "Debug exception", /* 1 */
55 "NMI interrupt", /* 2 */
56 "Breakpoint exception", /* 3 */
57 "Overflow exception", /* 4 */
58 "Bound range exception", /* 5 */
59 "Invalid opcode exception", /* 6 */
60 "Device not available exception", /* 7 */
61 "Double fault exception", /* 8 */
62 "Coprocessor segment overrun", /* 9 */
63 "Invalid TSS exception", /* 10 */
64 "Segment not present exception", /* 11 */
65 "Stack fault", /* 12 */
66 "General protection fault", /* 13 */
67 "Page fault", /* 14 */
68 "Unknown exception", /* 15 */
69 "Floating point exception", /* 16 */
70 "Alignment check exception", /* 17 */
71 "Machine check exception" /* 18 */
73 #define NB_TRAPS (sizeof(SIGNAL_traps) / sizeof(SIGNAL_traps[0]))
74 #endif
76 /* Linux sigaction function */
78 #if defined(linux) && defined(__i386__)
79 /* This is the sigaction structure from the Linux 2.1.20 kernel. */
81 #undef sa_handler
82 struct kernel_sigaction
84 void (*sa_handler)();
85 unsigned long sa_mask;
86 unsigned long sa_flags;
87 void (*sa_restorer)();
90 /* Similar to the sigaction function in libc, except it leaves alone the
91 restorer field, which is used to specify the signal stack address */
92 static inline int wine_sigaction( int sig, struct kernel_sigaction *new,
93 struct kernel_sigaction *old )
95 #ifdef __PIC__
96 __asm__ __volatile__( "pushl %%ebx\n\t"
97 "movl %2,%%ebx\n\t"
98 "int $0x80\n\t"
99 "popl %%ebx"
100 : "=a" (sig)
101 : "0" (SYS_sigaction),
102 "r" (sig),
103 "c" (new),
104 "d" (old) );
105 #else
106 __asm__ __volatile__( "int $0x80"
107 : "=a" (sig)
108 : "0" (SYS_sigaction),
109 "b" (sig),
110 "c" (new),
111 "d" (old) );
112 #endif /* __PIC__ */
113 if (sig>=0)
114 return 0;
115 errno = -sig;
116 return -1;
118 #endif /* linux && __i386__ */
120 /* Signal stack */
122 static char SIGNAL_Stack[16384];
123 static sigset_t async_signal_set;
125 /**********************************************************************
126 * SIGNAL_child
128 * wait4 terminated child processes
130 static HANDLER_DEF(SIGNAL_child)
132 HANDLER_INIT();
133 #ifdef HAVE_WAIT4
134 wait4( 0, NULL, WNOHANG, NULL);
135 #elif defined (HAVE_WAITPID)
136 /* I am sort-of guessing that this is the same as the wait4 call. */
137 waitpid (0, NULL, WNOHANG);
138 #else
139 wait(NULL);
140 #endif
144 /**********************************************************************
145 * SIGNAL_SetHandler
147 void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
149 int ret;
151 #if defined(linux) && defined(__i386__)
153 struct kernel_sigaction sig_act;
154 sig_act.sa_handler = func;
155 sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0;
156 sig_act.sa_mask = 0;
157 /* Point to the top of the stack, minus 4 just in case, and make
158 it aligned */
159 sig_act.sa_restorer =
160 (void (*)())((int)(SIGNAL_Stack + sizeof(SIGNAL_Stack) - 4) & ~3);
161 ret = wine_sigaction( sig, &sig_act, NULL );
163 #else /* linux && __i386__ */
165 struct sigaction sig_act;
166 sig_act.sa_handler = func;
167 sigemptyset( &sig_act.sa_mask );
169 # if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
170 sig_act.sa_flags = SA_ONSTACK;
171 # elif defined (__svr4__) || defined(_SCO_DS)
172 sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
173 # elif defined(__EMX__)
174 sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
175 # else
176 sig_act.sa_flags = 0;
177 # endif
178 ret = sigaction( sig, &sig_act, NULL );
180 #endif /* linux && __i386__ */
182 if (ret < 0)
184 perror( "sigaction" );
185 exit(1);
189 extern void stop_wait(int a);
190 extern void WINSOCK_sigio(int a);
191 extern void ASYNC_sigio(int a);
194 /**********************************************************************
195 * SIGNAL_MaskAsyncEvents
197 void SIGNAL_MaskAsyncEvents( BOOL flag )
199 sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &async_signal_set, NULL);
202 extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags );
204 /**********************************************************************
205 * SIGNAL_break
207 * Handle Ctrl-C and such
209 static HANDLER_DEF(SIGNAL_break)
211 HANDLER_INIT();
212 if (Options.debug && fnWINE_Debugger)
213 fnWINE_Debugger( signal, HANDLER_CONTEXT ); /* Enter our debugger */
214 else exit(0);
218 /**********************************************************************
219 * SIGNAL_trap
221 * SIGTRAP handler.
223 static HANDLER_DEF(SIGNAL_trap)
225 HANDLER_INIT();
226 if (fnWINE_Debugger)
227 fnWINE_Debugger( signal, HANDLER_CONTEXT ); /* Enter our debugger */
231 /**********************************************************************
232 * SIGNAL_fault
234 * Segfault handler.
236 static HANDLER_DEF(SIGNAL_fault)
238 const char *fault = "Segmentation fault";
239 HANDLER_INIT();
241 #ifdef __i386__
243 #if defined(TRAP_sig) && defined(CR2_sig)
244 if (TRAP_sig(HANDLER_CONTEXT) == 0x0e
245 && VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) ))
246 return;
247 #endif
248 #if defined(TRAP_sig)
249 /* We don't do alignment checks */
250 /* FIXME: if we get SEHs, pass the fault through them first? */
251 if (TRAP_sig(HANDLER_CONTEXT) == 0x11) {
252 if (EFL_sig(HANDLER_CONTEXT) & 0x00040000) {
253 /* Disable AC flag, return */
254 EFL_sig(HANDLER_CONTEXT) &= ~0x00040000;
255 return;
258 #endif
260 if (fnINSTR_EmulateInstruction &&
261 fnINSTR_EmulateInstruction( HANDLER_CONTEXT )
263 return;
265 #ifdef TRAP_sig
266 if (TRAP_sig( HANDLER_CONTEXT ) < NB_TRAPS)
267 fault = SIGNAL_traps[TRAP_sig( HANDLER_CONTEXT )];
268 #endif
269 if (IS_SELECTOR_SYSTEM(CS_sig(HANDLER_CONTEXT)))
271 MSG("%s in 32-bit code (0x%08lx).\n", fault, EIP_sig(HANDLER_CONTEXT));
273 else
275 MSG("%s in 16-bit code (%04x:%04lx).\n", fault,
276 (WORD)CS_sig(HANDLER_CONTEXT), EIP_sig(HANDLER_CONTEXT) );
278 #ifdef CR2_sig
279 MSG("Fault address is 0x%08lx\n",CR2_sig(HANDLER_CONTEXT));
280 #endif
281 #endif
283 if (fnWINE_Debugger)
284 fnWINE_Debugger( signal, HANDLER_CONTEXT );
285 else {
286 MSG("stopping pid %d due to unhandled %s.\n",getpid(),fault);
287 kill(getpid(),SIGSTOP);
292 /**********************************************************************
293 * SIGNAL_InitHandlers
295 void SIGNAL_InitHandlers(void)
297 SIGNAL_SetHandler( SIGINT, (void (*)())SIGNAL_break, 1);
298 SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
299 SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault, 1);
300 SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault, 1);
301 #ifdef SIGTRAP
302 SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); /* debugger */
303 #endif
304 SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap, 1); /* forced break*/
305 #ifdef SIGBUS
306 SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault, 1);
307 #endif
308 return;
311 /**********************************************************************
312 * SIGNAL_Init
314 BOOL SIGNAL_Init(void)
316 #ifdef HAVE_WORKING_SIGALTSTACK
317 struct sigaltstack ss;
318 ss.ss_sp = SIGNAL_Stack;
319 ss.ss_size = sizeof(SIGNAL_Stack);
320 ss.ss_flags = 0;
321 if (sigaltstack(&ss, NULL) < 0)
323 perror("sigaltstack");
324 /* fall through on error and try it differently */
326 #endif /* HAVE_SIGALTSTACK */
328 sigemptyset(&async_signal_set);
330 SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1);
331 #ifdef CONFIG_IPC
332 sigaddset(&async_signal_set, SIGUSR2);
333 SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); /* For IPC */
334 #endif
335 #ifdef SIGIO
336 sigaddset(&async_signal_set, SIGIO);
337 /* SIGNAL_SetHandler( SIGIO, (void (*)())WINSOCK_sigio, 0); */
338 SIGNAL_SetHandler( SIGIO, (void (*)())ASYNC_sigio, 0);
339 #endif
340 sigaddset(&async_signal_set, SIGALRM);
342 /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */
343 signal (SIGPIPE, SIG_IGN);
344 SIGNAL_InitHandlers();
345 return TRUE;