Release 970329
[wine/multimedia.git] / loader / signal.c
blobfd2203fb36425ca8ffcbb66e842f4c782823a8c9
1 #ifndef WINELIB
2 #include <stdio.h>
3 #include <stdlib.h>
4 #ifdef __GLIBC__
5 #include <linux/signal.h>
6 #else
7 #include <signal.h>
8 #endif
9 #include <string.h>
10 #include <errno.h>
11 #include <time.h>
12 #include <setjmp.h>
14 #include <sys/time.h>
15 #include <sys/timeb.h>
16 #include <sys/types.h>
17 #include <sys/wait.h>
19 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__svr4__) || defined(_SCO_DS) || defined(__EMX__)
20 #if !defined(_SCO_DS) && !defined(__EMX__)
21 #include <sys/syscall.h>
22 #endif
23 #include <sys/param.h>
24 #else
25 #include <syscall.h>
26 #endif
28 #include "debugger.h"
29 #include "options.h"
30 #include "sigcontext.h"
31 #include "win.h"
32 #include "winsock.h"
34 #if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
35 char * cstack[4096];
36 #endif
38 #ifdef linux
39 extern void ___sig_restore();
40 extern void ___masksig_restore();
42 /* Similar to the sigaction function in libc, except it leaves alone the
43 restorer field */
45 static int
46 wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
48 __asm__("int $0x80":"=a" (sig)
49 :"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
50 if (sig>=0)
51 return 0;
52 errno = -sig;
53 return -1;
55 #endif /* linux */
58 #ifdef linux
59 #define HANDLER_DEF(name) void name (int signal, SIGCONTEXT context_struct)
60 #define HANDLER_PROLOG SIGCONTEXT *context = &context_struct; (void)context; {
61 #define HANDLER_EPILOG }
62 #elif defined(__svr4__) || defined(_SCO_DS)
63 #define HANDLER_DEF(name) void name (int signal, void *siginfo, SIGCONTEXT *context)
64 #define HANDLER_PROLOG /* nothing */
65 #define HANDLER_EPILOG /* nothing */
66 #else
67 #define HANDLER_DEF(name) void name (int signal, int code, SIGCONTEXT *context)
68 #define HANDLER_PROLOG /* nothing */
69 #define HANDLER_EPILOG /* nothing */
70 #endif
72 extern BOOL32 INSTR_EmulateInstruction( SIGCONTEXT *context );
74 /**********************************************************************
75 * wine_timer
77 * SIGALRM handler.
79 static
80 HANDLER_DEF(wine_timer)
82 HANDLER_PROLOG;
83 /* Should do real-time timers here */
84 DOSMEM_Tick();
85 HANDLER_EPILOG;
88 /**********************************************************************
89 * SIGNAL_break
91 * Handle Ctrl-C and such
93 static
94 HANDLER_DEF(SIGNAL_break)
96 HANDLER_PROLOG;
97 if (Options.debug) wine_debug( signal, context ); /* Enter our debugger */
98 exit(0);
99 HANDLER_EPILOG;
102 /**********************************************************************
103 * SIGNAL_child
105 * wait4 terminated child processes
107 static
108 HANDLER_DEF(SIGNAL_child)
110 HANDLER_PROLOG;
111 #ifdef HAVE_WAIT4
112 wait4( 0, NULL, WNOHANG, NULL);
113 #elif defined (HAVE_WAITPID)
114 /* I am sort-of guessing that this is the same as the wait4 call. */
115 waitpid (0, NULL, WNOHANG);
116 #else
117 wait(NULL);
118 #endif
119 HANDLER_EPILOG;
123 /**********************************************************************
124 * SIGNAL_trap
126 * SIGTRAP handler.
128 static
129 HANDLER_DEF(SIGNAL_trap)
131 HANDLER_PROLOG;
132 wine_debug( signal, context ); /* Enter our debugger */
133 HANDLER_EPILOG;
137 /**********************************************************************
138 * SIGNAL_fault
140 * Segfault handler.
142 static
143 HANDLER_DEF(SIGNAL_fault)
145 HANDLER_PROLOG;
146 if (CS_sig(context) == WINE_CODE_SELECTOR)
148 fprintf( stderr, "Segmentation fault in Wine program (%x:%lx)."
149 " Please debug.\n",
150 CS_sig(context), EIP_sig(context) );
152 else
154 if (INSTR_EmulateInstruction( context )) return;
155 fprintf( stderr, "Segmentation fault in Windows program %x:%lx.\n",
156 CS_sig(context), EIP_sig(context) );
158 wine_debug( signal, context );
159 HANDLER_EPILOG;
163 /**********************************************************************
164 * SIGNAL_SetHandler
166 static void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
168 int ret;
169 struct sigaction sig_act;
171 #ifdef linux
172 sig_act.sa_handler = func;
173 sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0;
174 /* Point to the top of the stack, minus 4 just in case, and make
175 it aligned */
176 sig_act.sa_restorer =
177 (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
178 ret = wine_sigaction( sig, &sig_act, NULL );
179 #endif /* linux */
181 #if defined(__NetBSD__) || defined(__FreeBSD__)
182 sigset_t sig_mask;
183 sigemptyset(&sig_mask);
184 sig_act.sa_handler = func;
185 sig_act.sa_flags = SA_ONSTACK;
186 sig_act.sa_mask = sig_mask;
187 ret = sigaction( sig, &sig_act, NULL );
188 #endif /* __FreeBSD__ || __NetBSD__ */
190 #if defined (__svr4__) || defined(_SCO_DS)
191 sigset_t sig_mask;
192 sigemptyset(&sig_mask);
193 sig_act.sa_handler = func;
194 sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
195 sig_act.sa_mask = sig_mask;
196 ret = sigaction( sig, &sig_act, NULL );
197 #endif /* __svr4__ || _SCO_DS */
199 #if defined(__EMX__)
200 sigset_t sig_mask;
201 sigemptyset(&sig_mask);
202 sig_act.sa_handler = func;
203 sig_act.sa_flags = 0; /* FIXME: EMX has only SA_ACK and SA_SYSV */
204 sig_act.sa_mask = sig_mask;
205 ret = sigaction( sig, &sig_act, NULL );
206 #endif /* __EMX__ */
208 if (ret < 0)
210 perror( "sigaction" );
211 exit(1);
215 extern void stop_wait(int a);
216 extern void WINSOCK_sigio(int a);
219 /**********************************************************************
220 * SIGNAL_Init
222 BOOL32 SIGNAL_Init(void)
224 #if defined(__NetBSD__) || defined(__FreeBSD__)
225 struct sigaltstack ss;
227 if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) {
228 fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
229 MINSIGSTKSZ);
230 return FALSE;
232 ss.ss_size = MINSIGSTKSZ;
233 ss.ss_flags = 0;
234 if (sigaltstack(&ss, NULL) < 0) {
235 perror("sigstack");
236 return FALSE;
238 #endif /* __FreeBSD__ || __NetBSD__ */
240 #if defined (__svr4__) || defined(_SCO_DS)
241 struct sigaltstack ss;
243 if ((ss.ss_sp = malloc(SIGSTKSZ) ) == NULL) {
244 fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
245 SIGSTKSZ);
246 return FALSE;
248 ss.ss_size = SIGSTKSZ;
249 ss.ss_flags = 0;
250 if (sigaltstack(&ss, NULL) < 0) {
251 perror("sigstack");
252 return FALSE;
254 #endif /* __svr4__ || _SCO_DS */
256 SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer, 1);
257 SIGNAL_SetHandler( SIGINT, (void (*)())SIGNAL_break, 1);
258 SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1);
259 SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
260 SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault, 1);
261 SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault, 1);
262 SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); /* debugger */
263 SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap, 1); /* forced break */
264 #ifdef SIGBUS
265 SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault, 1);
266 #endif
267 #ifdef CONFIG_IPC
268 SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); /* For IPC */
269 #endif
270 #ifndef __EMX__ /* FIXME */
271 SIGNAL_SetHandler( SIGIO, (void (*)())WINSOCK_sigio, 0);
272 #endif
273 return TRUE;
277 /**********************************************************************
278 * SIGNAL_StartBIOSTimer
280 * Start the BIOS tick timer.
282 void SIGNAL_StartBIOSTimer(void)
284 #ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
285 struct itimerval vt_timer;
286 static int timer_started = 0;
288 if (timer_started) return;
289 timer_started = 1;
290 vt_timer.it_interval.tv_sec = 0;
291 vt_timer.it_interval.tv_usec = 54929;
292 vt_timer.it_value = vt_timer.it_interval;
294 setitimer(ITIMER_REAL, &vt_timer, NULL);
295 #endif
298 /**********************************************************************
299 * SIGNAL_MaskAsyncEvents
301 void SIGNAL_MaskAsyncEvents( BOOL32 flag )
303 sigset_t set;
304 sigemptyset(&set);
305 #ifndef __EMX__ /* FIXME */
306 sigaddset(&set, SIGIO);
307 #endif
308 sigaddset(&set, SIGUSR1);
309 #ifdef CONFIG_IPC
310 sigaddset(&set, SIGUSR2);
311 #endif
312 sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &set, NULL);
315 #endif /* ifndef WINELIB */