Release Win16Lock during PROCESS_Create.
[wine] / loader / signal.c
1 /*
2  * Wine signal handling
3  *
4  * Copyright 1995 Alexandre Julliard
5  */
6
7 #include "config.h"
8
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>
17
18 #include <sys/time.h>
19 #include <sys/timeb.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22
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
33
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"
42
43 void (*fnWINE_Debugger)(int,SIGCONTEXT*) = NULL;
44 void (*ctx_debug_call)(int sig,CONTEXT*ctx)=NULL;
45 BOOL (*fnINSTR_EmulateInstruction)(SIGCONTEXT*ctx)=NULL;
46
47
48 #ifdef __i386__
49
50 /* i386 specific faults */
51 static const char * const SIGNAL_traps[] =
52 {
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 */
72 };
73 #define NB_TRAPS  (sizeof(SIGNAL_traps) / sizeof(SIGNAL_traps[0]))
74 #endif
75
76 /* Linux sigaction function */
77
78 #if defined(linux) && defined(__i386__)
79 /* This is the sigaction structure from the Linux 2.1.20 kernel.  */
80
81 #undef sa_handler
82 struct kernel_sigaction
83 {
84     void (*sa_handler)();
85     unsigned long sa_mask;
86     unsigned long sa_flags;
87     void (*sa_restorer)();
88 };
89
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 )
94 {
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;
117 }
118 #endif /* linux && __i386__ */
119
120 /* Signal stack */
121
122 static char SIGNAL_Stack[16384];
123 static sigset_t async_signal_set;
124
125 /**********************************************************************
126  *              SIGNAL_child
127  * 
128  * wait4 terminated child processes
129  */
130 static HANDLER_DEF(SIGNAL_child)
131 {
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
141 }
142
143
144 /**********************************************************************
145  *              SIGNAL_SetHandler
146  */
147 void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
148 {
149     int ret;
150
151 #if defined(linux) && defined(__i386__)
152
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 );
162
163 #else  /* linux && __i386__ */
164
165     struct sigaction sig_act;
166     sig_act.sa_handler = func;
167     sigemptyset( &sig_act.sa_mask );
168
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 );
179
180 #endif  /* linux && __i386__ */
181
182     if (ret < 0)
183     {
184         perror( "sigaction" );
185         exit(1);
186     }
187 }
188
189 extern void stop_wait(int a);
190 extern void WINSOCK_sigio(int a);
191 extern void ASYNC_sigio(int a);
192
193
194 /**********************************************************************
195  *              SIGNAL_MaskAsyncEvents
196  */
197 void SIGNAL_MaskAsyncEvents( BOOL flag )
198 {
199   sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &async_signal_set, NULL);
200 }
201
202 extern void SIGNAL_SetHandler( int sig, void (*func)(), int flags );
203
204 /**********************************************************************
205  *              SIGNAL_break
206  * 
207  * Handle Ctrl-C and such
208  */
209 static HANDLER_DEF(SIGNAL_break)
210 {
211     HANDLER_INIT();
212     if (Options.debug && fnWINE_Debugger)
213         fnWINE_Debugger( signal, HANDLER_CONTEXT );  /* Enter our debugger */
214     else exit(0);
215 }
216
217
218 /**********************************************************************
219  *              SIGNAL_trap
220  *
221  * SIGTRAP handler.
222  */
223 static HANDLER_DEF(SIGNAL_trap)
224 {
225     HANDLER_INIT();
226     if (fnWINE_Debugger)
227         fnWINE_Debugger( signal, HANDLER_CONTEXT );  /* Enter our debugger */
228 }
229
230
231 /**********************************************************************
232  *              SIGNAL_fault
233  *
234  * Segfault handler.
235  */
236 static HANDLER_DEF(SIGNAL_fault)
237 {
238     const char *fault = "Segmentation fault";
239     HANDLER_INIT();
240
241 #ifdef __i386__
242
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;
256         }
257    }
258 #endif
259
260     if (fnINSTR_EmulateInstruction && 
261         fnINSTR_EmulateInstruction( HANDLER_CONTEXT )
262     )
263         return;
264
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)))
270     {
271         MSG("%s in 32-bit code (0x%08lx).\n", fault, EIP_sig(HANDLER_CONTEXT));
272     }
273     else
274     {
275         MSG("%s in 16-bit code (%04x:%04lx).\n", fault,
276             (WORD)CS_sig(HANDLER_CONTEXT), EIP_sig(HANDLER_CONTEXT) );
277     }
278 #ifdef CR2_sig
279     MSG("Fault address is 0x%08lx\n",CR2_sig(HANDLER_CONTEXT));
280 #endif
281 #endif
282
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);
288     }
289 }
290
291
292 /**********************************************************************
293  *              SIGNAL_InitHandlers
294  */
295 void SIGNAL_InitHandlers(void)
296 {
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;
309 }
310
311 /**********************************************************************
312  *              SIGNAL_Init
313  */
314 BOOL SIGNAL_Init(void)
315 {
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)
322     {
323         perror("sigaltstack");
324         /* fall through on error and try it differently */
325     }
326 #endif  /* HAVE_SIGALTSTACK */
327     
328     sigemptyset(&async_signal_set);
329
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);
341
342     /* ignore SIGPIPE so that WINSOCK can get a EPIPE error instead  */
343     signal (SIGPIPE, SIG_IGN);
344     SIGNAL_InitHandlers();
345     return TRUE;
346 }