blob: 8e4d863cb26a27c9845414d84671abb50c2b0488 [file] [log] [blame]
Alexandre Julliard641ee761997-08-04 16:34:36 +00001/*
2 * Wine signal handling
3 *
Marcus Meissner9faa7d71999-02-13 17:55:17 +00004 * Copyright 1995 Alexandre Julliard
Alexandre Julliard641ee761997-08-04 16:34:36 +00005 */
6
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00007#include "config.h"
8
Alexandre Julliard401710d1993-09-04 10:09:32 +00009#include <stdlib.h>
Marcus Meissner9faa7d71999-02-13 17:55:17 +000010#include <string.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000011#include <signal.h>
Alexandre Julliard234bc241994-12-10 13:02:28 +000012#include <string.h>
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000013#include <errno.h>
Alexandre Julliard401710d1993-09-04 10:09:32 +000014#include <time.h>
Alexandre Julliard3a405ba1994-10-30 16:25:19 +000015#include <setjmp.h>
Alexandre Julliard401710d1993-09-04 10:09:32 +000016
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000017#include <sys/time.h>
18#include <sys/timeb.h>
Alexandre Julliardb1bac321996-12-15 19:45:59 +000019#include <sys/types.h>
20#include <sys/wait.h>
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000021
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000022#ifdef HAVE_SYS_PARAM_H
23# include <sys/param.h>
Alexandre Julliard8664b891996-04-05 14:58:24 +000024#endif
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000025#ifdef HAVE_SYSCALL_H
26# include <syscall.h>
Alexandre Julliard5f721f81994-01-04 20:14:34 +000027#else
Alexandre Julliardc7c217b1998-04-13 12:21:30 +000028# ifdef HAVE_SYS_SYSCALL_H
29# include <sys/syscall.h>
30# endif
Alexandre Julliard5f721f81994-01-04 20:14:34 +000031#endif
Alexandre Julliard8d24ae61994-04-05 21:42:43 +000032
Alexandre Julliardb1bac321996-12-15 19:45:59 +000033#include "winsock.h"
Marcus Meissner9faa7d71999-02-13 17:55:17 +000034#include "global.h"
35#include "options.h"
36#include "debugger.h"
37#include "miscemu.h"
38#include "dosexe.h"
39#include "thread.h"
40#include "debug.h"
41
42void (*fnWINE_Debugger)(int,SIGCONTEXT*) = NULL;
43void (*ctx_debug_call)(int sig,CONTEXT*ctx)=NULL;
44BOOL32 (*fnINSTR_EmulateInstruction)(SIGCONTEXT*ctx)=NULL;
45
46#ifdef __i386__
47
48/* i386 specific faults */
49static const char * const SIGNAL_traps[] =
50{
51 "Division by zero exception", /* 0 */
52 "Debug exception", /* 1 */
53 "NMI interrupt", /* 2 */
54 "Breakpoint exception", /* 3 */
55 "Overflow exception", /* 4 */
56 "Bound range exception", /* 5 */
57 "Invalid opcode exception", /* 6 */
58 "Device not available exception", /* 7 */
59 "Double fault exception", /* 8 */
60 "Coprocessor segment overrun", /* 9 */
61 "Invalid TSS exception", /* 10 */
62 "Segment not present exception", /* 11 */
63 "Stack fault", /* 12 */
64 "General protection fault", /* 13 */
65 "Page fault", /* 14 */
66 "Unknown exception", /* 15 */
67 "Floating point exception", /* 16 */
68 "Alignment check exception", /* 17 */
69 "Machine check exception" /* 18 */
70};
71#define NB_TRAPS (sizeof(SIGNAL_traps) / sizeof(SIGNAL_traps[0]))
72#endif
Alexandre Julliardaca05781994-10-17 18:12:41 +000073
Alexandre Julliard641ee761997-08-04 16:34:36 +000074/* Linux sigaction function */
Alexandre Julliard401710d1993-09-04 10:09:32 +000075
Alexandre Julliard641ee761997-08-04 16:34:36 +000076#if defined(linux) && defined(__i386__)
Alexandre Julliard889f7421997-04-15 17:19:52 +000077/* This is the sigaction structure from the Linux 2.1.20 kernel. */
Alexandre Julliarda11d7b11998-03-01 20:05:02 +000078#undef sa_handler
Alexandre Julliard641ee761997-08-04 16:34:36 +000079struct kernel_sigaction
80{
81 void (*sa_handler)();
82 unsigned long sa_mask;
83 unsigned long sa_flags;
84 void (*sa_restorer)();
Alexandre Julliard889f7421997-04-15 17:19:52 +000085};
86
Alexandre Julliard401710d1993-09-04 10:09:32 +000087/* Similar to the sigaction function in libc, except it leaves alone the
Alexandre Julliard641ee761997-08-04 16:34:36 +000088 restorer field, which is used to specify the signal stack address */
89static __inline__ int wine_sigaction( int sig, struct kernel_sigaction *new,
90 struct kernel_sigaction *old )
Alexandre Julliard401710d1993-09-04 10:09:32 +000091{
Alexandre Julliard670cdc41997-08-24 16:00:30 +000092#ifdef __PIC__
93 __asm__ __volatile__( "pushl %%ebx\n\t"
94 "movl %2,%%ebx\n\t"
95 "int $0x80\n\t"
96 "popl %%ebx"
97 : "=a" (sig)
98 : "0" (SYS_sigaction),
Marcus Meissner4ede2961999-02-21 18:18:42 +000099 "r" (sig),
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000100 "c" (new),
101 "d" (old) );
102#else
Alexandre Julliard641ee761997-08-04 16:34:36 +0000103 __asm__ __volatile__( "int $0x80"
104 : "=a" (sig)
105 : "0" (SYS_sigaction),
106 "b" (sig),
107 "c" (new),
108 "d" (old) );
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000109#endif /* __PIC__ */
Alexandre Julliard641ee761997-08-04 16:34:36 +0000110 if (sig>=0)
111 return 0;
112 errno = -sig;
113 return -1;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000114}
Alexandre Julliard641ee761997-08-04 16:34:36 +0000115#endif /* linux && __i386__ */
Alexandre Julliard21979011997-03-05 08:22:35 +0000116
Alexandre Julliard641ee761997-08-04 16:34:36 +0000117/* Signal stack */
118
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000119static char SIGNAL_Stack[16384];
Alexandre Julliard54c27111998-03-29 19:44:57 +0000120static sigset_t async_signal_set;
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000121
122/**********************************************************************
123 * SIGNAL_child
124 *
125 * wait4 terminated child processes
126 */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000127static HANDLER_DEF(SIGNAL_child)
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000128{
Alexandre Julliarda69b88b1998-03-15 20:29:56 +0000129 HANDLER_INIT();
Alexandre Julliard21979011997-03-05 08:22:35 +0000130#ifdef HAVE_WAIT4
Alexandre Julliard641ee761997-08-04 16:34:36 +0000131 wait4( 0, NULL, WNOHANG, NULL);
Alexandre Julliard21979011997-03-05 08:22:35 +0000132#elif defined (HAVE_WAITPID)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000133 /* I am sort-of guessing that this is the same as the wait4 call. */
134 waitpid (0, NULL, WNOHANG);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000135#else
Alexandre Julliard641ee761997-08-04 16:34:36 +0000136 wait(NULL);
Alexandre Julliardc6c09441997-01-12 18:32:19 +0000137#endif
Alexandre Julliard401710d1993-09-04 10:09:32 +0000138}
139
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000140
141/**********************************************************************
142 * SIGNAL_SetHandler
143 */
Alexandre Julliard641ee761997-08-04 16:34:36 +0000144void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000145{
146 int ret;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000147
Alexandre Julliard641ee761997-08-04 16:34:36 +0000148#if defined(linux) && defined(__i386__)
149
Alexandre Julliard889f7421997-04-15 17:19:52 +0000150 struct kernel_sigaction sig_act;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000151 sig_act.sa_handler = func;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000152 sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0;
153 sig_act.sa_mask = 0;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000154 /* Point to the top of the stack, minus 4 just in case, and make
155 it aligned */
156 sig_act.sa_restorer =
Alexandre Julliard641ee761997-08-04 16:34:36 +0000157 (void (*)())((int)(SIGNAL_Stack + sizeof(SIGNAL_Stack) - 4) & ~3);
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000158 ret = wine_sigaction( sig, &sig_act, NULL );
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000159
Alexandre Julliard641ee761997-08-04 16:34:36 +0000160#else /* linux && __i386__ */
161
Alexandre Julliard889f7421997-04-15 17:19:52 +0000162 struct sigaction sig_act;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000163 sig_act.sa_handler = func;
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000164 sigemptyset( &sig_act.sa_mask );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000165
166# if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000167 sig_act.sa_flags = SA_ONSTACK;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000168# elif defined (__svr4__) || defined(_SCO_DS)
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000169 sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000170# elif defined(__EMX__)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000171 sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
Alexandre Julliard641ee761997-08-04 16:34:36 +0000172# else
173 sig_act.sa_flags = 0;
174# endif
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000175 ret = sigaction( sig, &sig_act, NULL );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000176
177#endif /* linux && __i386__ */
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000178
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000179 if (ret < 0)
180 {
181 perror( "sigaction" );
182 exit(1);
183 }
184}
185
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000186extern void stop_wait(int a);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000187extern void WINSOCK_sigio(int a);
Marcus Meissnerad7538b1998-12-14 18:15:10 +0000188extern void ASYNC_sigio(int a);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000189
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000190
191/**********************************************************************
Marcus Meissner9faa7d71999-02-13 17:55:17 +0000192 * SIGNAL_MaskAsyncEvents
193 */
194void SIGNAL_MaskAsyncEvents( BOOL32 flag )
195{
196 sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &async_signal_set, NULL);
197}
198
199extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags );
200
201/**********************************************************************
202 * SIGNAL_break
203 *
204 * Handle Ctrl-C and such
205 */
206static HANDLER_DEF(SIGNAL_break)
207{
208 HANDLER_INIT();
209 if (Options.debug && fnWINE_Debugger)
210 fnWINE_Debugger( signal, HANDLER_CONTEXT ); /* Enter our debugger */
211 else exit(0);
212}
213
214
215/**********************************************************************
216 * SIGNAL_trap
217 *
218 * SIGTRAP handler.
219 */
220static HANDLER_DEF(SIGNAL_trap)
221{
222 HANDLER_INIT();
223 if (fnWINE_Debugger)
224 fnWINE_Debugger( signal, HANDLER_CONTEXT ); /* Enter our debugger */
225}
226
227
228/**********************************************************************
229 * SIGNAL_fault
230 *
231 * Segfault handler.
232 */
233static HANDLER_DEF(SIGNAL_fault)
234{
235 const char *fault = "Segmentation fault";
236 HANDLER_INIT();
237
238#ifdef __i386__
239
240#if defined(TRAP_sig) && defined(CR2_sig)
241 if (TRAP_sig(HANDLER_CONTEXT) == 0x0e
242 && VIRTUAL_HandleFault( (LPVOID)CR2_sig(HANDLER_CONTEXT) ))
243 return;
244#endif
245
246 if (fnINSTR_EmulateInstruction &&
247 fnINSTR_EmulateInstruction( HANDLER_CONTEXT )
248 )
249 return;
250
251#ifdef TRAP_sig
252 if (TRAP_sig( HANDLER_CONTEXT ) < NB_TRAPS)
253 fault = SIGNAL_traps[TRAP_sig( HANDLER_CONTEXT )];
254#endif
255 if (IS_SELECTOR_SYSTEM(CS_sig(HANDLER_CONTEXT)))
256 {
257 MSG("%s in 32-bit code (0x%08lx).\n", fault, EIP_sig(HANDLER_CONTEXT));
258 }
259 else
260 {
261 MSG("%s in 16-bit code (%04x:%04lx).\n", fault,
262 (WORD)CS_sig(HANDLER_CONTEXT), EIP_sig(HANDLER_CONTEXT) );
263 }
264#ifdef CR2_sig
265 MSG("Fault address is 0x%08lx\n",CR2_sig(HANDLER_CONTEXT));
266#endif
267#endif
268
269 if (fnWINE_Debugger)
270 fnWINE_Debugger( signal, HANDLER_CONTEXT );
271}
272
273
274/**********************************************************************
275 * SIGNAL_InitHandlers
276 */
277void SIGNAL_InitHandlers(void)
278{
279 SIGNAL_SetHandler( SIGINT, (void (*)())SIGNAL_break, 1);
280 SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
281 SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault, 1);
282 SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault, 1);
283 SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); /* debugger */
284 SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap, 1); /* forced break*/
285#ifdef SIGBUS
286 SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault, 1);
287#endif
288 return;
289}
290
291/**********************************************************************
Alexandre Julliardca22b331996-07-12 19:02:39 +0000292 * SIGNAL_Init
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000293 */
Alexandre Julliardca22b331996-07-12 19:02:39 +0000294BOOL32 SIGNAL_Init(void)
Alexandre Julliard8d24ae61994-04-05 21:42:43 +0000295{
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000296#ifdef HAVE_WORKING_SIGALTSTACK
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000297 struct sigaltstack ss;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000298 ss.ss_sp = SIGNAL_Stack;
299 ss.ss_size = sizeof(SIGNAL_Stack);
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000300 ss.ss_flags = 0;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000301 if (sigaltstack(&ss, NULL) < 0)
302 {
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000303 perror("sigstack");
Alexandre Julliardca22b331996-07-12 19:02:39 +0000304 return FALSE;
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000305 }
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000306#endif /* HAVE_SIGALTSTACK */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000307
Alexandre Julliardc7c217b1998-04-13 12:21:30 +0000308 sigemptyset(&async_signal_set);
309
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000310 SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1);
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000311#ifdef CONFIG_IPC
Alexandre Julliard54c27111998-03-29 19:44:57 +0000312 sigaddset(&async_signal_set, SIGUSR2);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000313 SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); /* For IPC */
Alexandre Julliardb817f4f1996-03-14 18:08:34 +0000314#endif
Alexandre Julliard641ee761997-08-04 16:34:36 +0000315#ifdef SIGIO
Alexandre Julliard54c27111998-03-29 19:44:57 +0000316 sigaddset(&async_signal_set, SIGIO);
Marcus Meissnerad7538b1998-12-14 18:15:10 +0000317/* SIGNAL_SetHandler( SIGIO, (void (*)())WINSOCK_sigio, 0); */
318 SIGNAL_SetHandler( SIGIO, (void (*)())ASYNC_sigio, 0);
Alexandre Julliard01d63461997-01-20 19:43:45 +0000319#endif
Alexandre Julliard54c27111998-03-29 19:44:57 +0000320 sigaddset(&async_signal_set, SIGALRM);
321
322 /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead */
323 signal (SIGPIPE, SIG_IGN);
Marcus Meissner9faa7d71999-02-13 17:55:17 +0000324 SIGNAL_InitHandlers();
Alexandre Julliardca22b331996-07-12 19:02:39 +0000325 return TRUE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000326}