Release 961222
[wine/multimedia.git] / loader / signal.c
blob9d11530fc7c0a0416d175c7309b1640d65569573
1 #ifndef WINELIB
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <signal.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <time.h>
8 #include <setjmp.h>
10 #include <sys/time.h>
11 #include <sys/timeb.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
15 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__svr4__) || defined(_SCO_DS)
16 #ifndef _SCO_DS
17 #include <sys/syscall.h>
18 #endif
19 #include <sys/param.h>
20 #else
21 #include <syscall.h>
22 #endif
24 #include "debugger.h"
25 #include "miscemu.h"
26 #include "options.h"
27 #include "registers.h"
28 #include "win.h"
29 #include "winsock.h"
31 #if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
32 char * cstack[4096];
33 #endif
35 #ifdef linux
36 extern void ___sig_restore();
37 extern void ___masksig_restore();
39 /* Similar to the sigaction function in libc, except it leaves alone the
40 restorer field */
42 static int
43 wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
45 __asm__("int $0x80":"=a" (sig)
46 :"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
47 if (sig>=0)
48 return 0;
49 errno = -sig;
50 return -1;
52 #endif
55 /**********************************************************************
56 * wine_timer
58 * SIGALRM handler.
60 #ifdef linux
61 static void wine_timer(int signal, SIGCONTEXT context_struct)
63 #elif defined(__svr4__)
64 static void wine_timer(int signal, void *siginfo, SIGCONTEXT *context)
66 #else
67 static void wine_timer(int signal, int code, SIGCONTEXT *context)
69 #endif
70 /* Should do real-time timers here */
72 DOSMEM_Tick();
75 /**********************************************************************
76 * SIGNAL_break
78 * Handle Ctrl-C and such
80 #ifdef linux
81 static void SIGNAL_break(int signal, SIGCONTEXT context_struct)
83 SIGCONTEXT *context = &context_struct;
84 #elif defined(__svr4__) || defined(_SCO_DS)
85 static void SIGNAL_break(int signal, void *siginfo, SIGCONTEXT *context)
87 #else
88 static void SIGNAL_break(int signal, int code, SIGCONTEXT *context)
90 #endif
91 if (Options.debug) wine_debug( signal, context ); /* Enter our debugger */
92 exit(0);
95 /**********************************************************************
96 * SIGNAL_child
98 * wait4 terminated child processes
100 static void SIGNAL_child(void)
102 wait4( 0, NULL, WNOHANG, NULL);
106 /**********************************************************************
107 * SIGNAL_trap
109 * SIGTRAP handler.
111 #ifdef linux
112 static void SIGNAL_trap(int signal, SIGCONTEXT context_struct)
114 SIGCONTEXT *context = &context_struct;
115 #elif defined(__svr4__) || defined(_SCO_DS)
116 static void SIGNAL_trap(int signal, void *siginfo, SIGCONTEXT *context)
118 #else
119 static void SIGNAL_trap(int signal, int code, SIGCONTEXT *context)
121 #endif
122 wine_debug( signal, context ); /* Enter our debugger */
126 /**********************************************************************
127 * SIGNAL_fault
129 * Segfault handler.
131 #ifdef linux
132 static void SIGNAL_fault(int signal, SIGCONTEXT context_struct)
134 SIGCONTEXT *context = &context_struct;
135 #elif defined(__svr4__) || defined(_SCO_DS)
136 static void SIGNAL_fault(int signal, void *siginfo, SIGCONTEXT *context)
138 #else
139 static void SIGNAL_fault(int signal, int code, SIGCONTEXT *context)
141 #endif
142 if (CS_reg(context) == WINE_CODE_SELECTOR)
144 fprintf( stderr, "Segmentation fault in Wine program (%x:%lx)."
145 " Please debug.\n",
146 CS_reg(context), EIP_reg(context) );
148 else
150 if (INSTR_EmulateInstruction( context )) return;
151 fprintf( stderr, "Segmentation fault in Windows program %x:%lx.\n",
152 CS_reg(context), EIP_reg(context) );
154 wine_debug( signal, context );
158 /**********************************************************************
159 * SIGNAL_SetHandler
161 static void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
163 int ret;
164 struct sigaction sig_act;
166 #ifdef linux
167 sig_act.sa_handler = func;
168 sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0;
169 /* Point to the top of the stack, minus 4 just in case, and make
170 it aligned */
171 sig_act.sa_restorer =
172 (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
173 ret = wine_sigaction( sig, &sig_act, NULL );
174 #endif /* linux */
176 #if defined(__NetBSD__) || defined(__FreeBSD__)
177 sigset_t sig_mask;
178 sigemptyset(&sig_mask);
179 sig_act.sa_handler = func;
180 sig_act.sa_flags = SA_ONSTACK;
181 sig_act.sa_mask = sig_mask;
182 ret = sigaction( sig, &sig_act, NULL );
183 #endif /* __FreeBSD__ || __NetBSD__ */
185 #if defined (__svr4__) || defined(_SCO_DS)
186 sigset_t sig_mask;
187 sigemptyset(&sig_mask);
188 sig_act.sa_handler = func;
189 sig_act.sa_flags = SA_SIGINFO | SA_ONSTACK | SA_RESTART;
190 sig_act.sa_mask = sig_mask;
191 ret = sigaction( sig, &sig_act, NULL );
192 #endif /* __svr4__ || _SCO_DS */
194 if (ret < 0)
196 perror( "sigaction" );
197 exit(1);
201 extern void stop_wait(int a);
202 extern void WINSOCK_sigio(int a);
205 /**********************************************************************
206 * SIGNAL_Init
208 BOOL32 SIGNAL_Init(void)
210 #if defined(__NetBSD__) || defined(__FreeBSD__)
211 struct sigaltstack ss;
213 if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) {
214 fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
215 MINSIGSTKSZ);
216 return FALSE;
218 ss.ss_size = MINSIGSTKSZ;
219 ss.ss_flags = 0;
220 if (sigaltstack(&ss, NULL) < 0) {
221 perror("sigstack");
222 return FALSE;
224 #endif /* __FreeBSD__ || __NetBSD__ */
226 #if defined (__svr4__) || defined(_SCO_DS)
227 struct sigaltstack ss;
229 if ((ss.ss_sp = malloc(SIGSTKSZ) ) == NULL) {
230 fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
231 SIGSTKSZ);
232 return FALSE;
234 ss.ss_size = SIGSTKSZ;
235 ss.ss_flags = 0;
236 if (sigaltstack(&ss, NULL) < 0) {
237 perror("sigstack");
238 return FALSE;
240 #endif /* __svr4__ || _SCO_DS */
242 SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer, 1);
243 SIGNAL_SetHandler( SIGINT, (void (*)())SIGNAL_break, 1);
244 SIGNAL_SetHandler( SIGCHLD, (void (*)())SIGNAL_child, 1);
245 SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
246 SIGNAL_SetHandler( SIGILL, (void (*)())SIGNAL_fault, 1);
247 SIGNAL_SetHandler( SIGFPE, (void (*)())SIGNAL_fault, 1);
248 SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); /* debugger */
249 SIGNAL_SetHandler( SIGHUP, (void (*)())SIGNAL_trap, 1); /* forced break */
250 #ifdef SIGBUS
251 SIGNAL_SetHandler( SIGBUS, (void (*)())SIGNAL_fault, 1);
252 #endif
253 #ifdef CONFIG_IPC
254 SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); /* For IPC */
255 #endif
256 SIGNAL_SetHandler( SIGIO, (void (*)())WINSOCK_sigio, 0);
257 return TRUE;
261 /**********************************************************************
262 * SIGNAL_StartBIOSTimer
264 * Start the BIOS tick timer.
266 void SIGNAL_StartBIOSTimer(void)
268 struct itimerval vt_timer;
269 static int timer_started = 0;
271 if (timer_started) return;
272 timer_started = 1;
273 vt_timer.it_interval.tv_sec = 0;
274 vt_timer.it_interval.tv_usec = 54929;
275 vt_timer.it_value = vt_timer.it_interval;
277 setitimer(ITIMER_REAL, &vt_timer, NULL);
280 /**********************************************************************
281 * SIGNAL_MaskAsyncEvents
283 void SIGNAL_MaskAsyncEvents( BOOL32 flag )
285 sigset_t set;
286 sigemptyset(&set);
287 sigaddset(&set, SIGIO);
288 sigaddset(&set, SIGUSR1);
289 #ifdef CONFIG_IPC
290 sigaddset(&set, SIGUSR2);
291 #endif
292 sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &set, NULL);
295 #endif /* ifndef WINELIB */