]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/exceptions.cc
* environ.cc (environ_init): Avoid a compiler warning.
[newlib-cygwin.git] / winsup / cygwin / exceptions.cc
CommitLineData
1fd5e000
CF
1/* exceptions.cc
2
33ad2bf9 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
1fd5e000
CF
4
5This file is part of Cygwin.
6
7This software is a copyrighted work licensed under the terms of the
8Cygwin license. Please consult the file "CYGWIN_LICENSE" for
9details. */
10
4c8d72de 11#include "winsup.h"
bccd5e0d 12#include <imagehlp.h>
1fd5e000 13#include <errno.h>
e2b3dc25 14#include <stdlib.h>
1fd5e000 15
1fd5e000 16#include "exceptions.h"
bccd5e0d
CF
17#include "sync.h"
18#include "sigproc.h"
e2ebe117 19#include "pinfo.h"
9e2baf8d 20#include "cygerrno.h"
bccd5e0d 21#include "perthread.h"
29ac7f89 22#include "shared_info.h"
f0338f54
CF
23#include "perprocess.h"
24#include "security.h"
1fd5e000 25
c0188ae7
CF
26#define CALL_HANDLER_RETRY 20
27
3d0ba393 28char debugger_command[2 * MAX_PATH + 20];
1fd5e000
CF
29
30extern "C" {
31static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *);
32extern void sigreturn ();
33extern void sigdelayed ();
c3d62298 34extern void sigdelayed0 ();
1fd5e000 35extern void siglast ();
dd11f11f 36extern DWORD __no_sig_start, __no_sig_end;
1fd5e000
CF
37};
38
f9f2ed0e
CF
39extern DWORD sigtid;
40
c0a8e8d0
CF
41extern HANDLE hExeced;
42extern DWORD dwExeced;
43
1fd5e000 44static BOOL WINAPI ctrl_c_handler (DWORD);
e06f5813 45static void signal_exit (int) __attribute__ ((noreturn));
f02f1f14
CF
46static char windows_system_directory[1024];
47static size_t windows_system_directory_length;
1fd5e000
CF
48
49/* This is set to indicate that we have already exited. */
50
51static NO_COPY int exit_already = 0;
52static NO_COPY muto *mask_sync = NULL;
53
0cda2f46 54HMODULE NO_COPY cygwin_hmodule;
1fd5e000 55
bc6ed549 56NO_COPY static struct
1fd5e000
CF
57{
58 unsigned int code;
59 const char *name;
bc6ed549 60} status_info[] =
1fd5e000
CF
61{
62#define X(s) s, #s
63 { X (STATUS_ABANDONED_WAIT_0) },
64 { X (STATUS_ACCESS_VIOLATION) },
65 { X (STATUS_ARRAY_BOUNDS_EXCEEDED) },
66 { X (STATUS_BREAKPOINT) },
67 { X (STATUS_CONTROL_C_EXIT) },
68 { X (STATUS_DATATYPE_MISALIGNMENT) },
69 { X (STATUS_FLOAT_DENORMAL_OPERAND) },
70 { X (STATUS_FLOAT_DIVIDE_BY_ZERO) },
71 { X (STATUS_FLOAT_INEXACT_RESULT) },
72 { X (STATUS_FLOAT_INVALID_OPERATION) },
73 { X (STATUS_FLOAT_OVERFLOW) },
74 { X (STATUS_FLOAT_STACK_CHECK) },
75 { X (STATUS_FLOAT_UNDERFLOW) },
76 { X (STATUS_GUARD_PAGE_VIOLATION) },
77 { X (STATUS_ILLEGAL_INSTRUCTION) },
78 { X (STATUS_INTEGER_DIVIDE_BY_ZERO) },
79 { X (STATUS_INTEGER_OVERFLOW) },
80 { X (STATUS_INVALID_DISPOSITION) },
81 { X (STATUS_IN_PAGE_ERROR) },
82 { X (STATUS_NONCONTINUABLE_EXCEPTION) },
83 { X (STATUS_NO_MEMORY) },
84 { X (STATUS_PENDING) },
85 { X (STATUS_PRIVILEGED_INSTRUCTION) },
86 { X (STATUS_SINGLE_STEP) },
87 { X (STATUS_STACK_OVERFLOW) },
88 { X (STATUS_TIMEOUT) },
89 { X (STATUS_USER_APC) },
90 { X (STATUS_WAIT_0) },
91 { 0, 0 }
92#undef X
93};
94
95/* Initialization code. */
96
97#ifdef __i386__
98
99// Set up the exception handler for the current thread. The PowerPC & Mips
100// use compiler generated tables to set up the exception handlers for each
101// region of code, and the kernel walks the call list until it finds a region
102// of code that handles exceptions. The x86 on the other hand uses segment
103// register fs, offset 0 to point to the current exception handler.
104
105asm (".equ __except_list,0");
106
107extern exception_list *_except_list asm ("%fs:__except_list");
108
109static void
110init_exception_handler (exception_list *el)
111{
112 el->handler = handle_exceptions;
113 el->prev = _except_list;
114 _except_list = el;
115}
1fd5e000
CF
116#endif
117
118void
c0a8e8d0 119early_stuff_init ()
1fd5e000 120{
c0a8e8d0
CF
121 (void) SetConsoleCtrlHandler (ctrl_c_handler, FALSE);
122 if (!SetConsoleCtrlHandler (ctrl_c_handler, TRUE))
123 system_printf ("SetConsoleCtrlHandler failed, %E");
124
1fd5e000
CF
125 /* Initialize global security attribute stuff */
126
127 sec_none.nLength = sec_none_nih.nLength =
128 sec_all.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);
129 sec_none.bInheritHandle = sec_all.bInheritHandle = TRUE;
130 sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE;
131 sec_none.lpSecurityDescriptor = sec_none_nih.lpSecurityDescriptor = NULL;
132 sec_all.lpSecurityDescriptor = sec_all_nih.lpSecurityDescriptor =
133 get_null_sd ();
1fd5e000
CF
134}
135
136extern "C" void
137init_exceptions (exception_list *el)
138{
8abeff1e 139 init_exception_handler (el);
1fd5e000
CF
140}
141
142extern "C" void
143error_start_init (const char *buf)
144{
145 if (!buf || !*buf)
146 {
147 debugger_command[0] = '\0';
148 return;
149 }
150
56a42791
CF
151 char pgm[MAX_PATH + 1];
152 if (!GetModuleFileName (NULL, pgm, MAX_PATH))
153 strcpy (pgm, "cygwin1.dll");
154 for (char *p = strchr (pgm, '\\'); p; p = strchr (p, '\\'))
155 *p = '/';
1fd5e000 156
56a42791 157 __small_sprintf (debugger_command, "%s %s", buf, pgm);
1fd5e000
CF
158}
159
8abeff1e
CF
160static void
161open_stackdumpfile ()
162{
163 if (myself->progname[0])
164 {
165 const char *p;
166 /* write to progname.stackdump if possible */
b2bfade3
CF
167 if (!myself->progname[0])
168 p = "unknown";
169 else if ((p = strrchr (myself->progname, '\\')))
8abeff1e
CF
170 p++;
171 else
172 p = myself->progname;
173 char corefile[strlen (p) + sizeof (".stackdump")];
174 __small_sprintf (corefile, "%s.stackdump", p);
175 HANDLE h = CreateFile (corefile, GENERIC_WRITE, 0, &sec_none_nih,
176 CREATE_ALWAYS, 0, 0);
177 if (h != INVALID_HANDLE_VALUE)
178 {
ebd645e7
CF
179 if (!myself->ppid_handle)
180 system_printf ("Dumping stack trace to %s", corefile);
181 else
182 debug_printf ("Dumping stack trace to %s", corefile);
8abeff1e
CF
183 SetStdHandle (STD_ERROR_HANDLE, h);
184 }
185 }
186}
187
1fd5e000
CF
188/* Utilities for dumping the stack, etc. */
189
190static void
191exception (EXCEPTION_RECORD *e, CONTEXT *in)
192{
20d7f758 193 const char *exception_name = NULL;
1fd5e000
CF
194
195 if (e)
196 {
197 for (int i = 0; status_info[i].name; i++)
198 {
199 if (status_info[i].code == e->ExceptionCode)
200 {
201 exception_name = status_info[i].name;
202 break;
203 }
204 }
205 }
206
207#ifdef __i386__
208#define HAVE_STATUS
209 if (exception_name)
210 small_printf ("Exception: %s at eip=%08x\r\n", exception_name, in->Eip);
211 else
212 small_printf ("Exception %d at eip=%08x\r\n", e->ExceptionCode, in->Eip);
213 small_printf ("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n",
214 in->Eax, in->Ebx, in->Ecx, in->Edx, in->Esi, in->Edi);
215 small_printf ("ebp=%08x esp=%08x program=%s\r\n",
216 in->Ebp, in->Esp, myself->progname);
217 small_printf ("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n",
218 in->SegCs, in->SegDs, in->SegEs, in->SegFs, in->SegGs, in->SegSs);
219#endif
220
221#ifndef HAVE_STATUS
222 system_printf ("Had an exception");
223#endif
224}
225
1fd5e000
CF
226#ifdef __i386__
227/* Print a stack backtrace. */
228
229#define HAVE_STACK_TRACE
230
1fd5e000
CF
231/* A class for manipulating the stack. */
232class stack_info
233{
1d613351 234 int walk (); /* Uses the "old" method */
8366e93b 235 char *next_offset () {return *((char **) sf.AddrFrame.Offset);}
f598d941
CF
236 bool needargs;
237 DWORD dummy_frame;
1fd5e000 238public:
f598d941
CF
239 STACKFRAME sf; /* For storing the stack information */
240 void init (DWORD, bool, bool); /* Called the first time that stack info is needed */
af1dc7cc 241
1fd5e000 242 /* Postfix ++ iterates over the stack, returning zero when nothing is left. */
af1dc7cc 243 int operator ++(int) { return this->walk (); }
1fd5e000
CF
244};
245
246/* The number of parameters used in STACKFRAME */
1d613351 247#define NPARAMS (sizeof (thestack.sf.Params) / sizeof (thestack.sf.Params[0]))
1fd5e000
CF
248
249/* This is the main stack frame info for this process. */
af1dc7cc 250static NO_COPY stack_info thestack;
ac944e37 251static signal_dispatch sigsave;
1fd5e000
CF
252
253/* Initialize everything needed to start iterating. */
254void
f598d941 255stack_info::init (DWORD ebp, bool wantargs, bool goodframe)
1fd5e000 256{
8abeff1e 257# define debp ((DWORD *) ebp)
1d613351 258 memset (&sf, 0, sizeof (sf));
f598d941
CF
259 if (!goodframe)
260 sf.AddrFrame.Offset = ebp;
261 else
262 {
263 dummy_frame = ebp;
264 sf.AddrFrame.Offset = (DWORD) &dummy_frame;
265 }
8abeff1e 266 sf.AddrReturn.Offset = debp[1];
1fd5e000 267 sf.AddrFrame.Mode = AddrModeFlat;
f598d941 268 needargs = wantargs;
8abeff1e 269# undef debp
1fd5e000
CF
270}
271
272/* Walk the stack by looking at successive stored 'bp' frames.
273 This is not foolproof. */
274int
af1dc7cc 275stack_info::walk ()
1fd5e000
CF
276{
277 char **ebp;
f598d941 278 if ((ebp = (char **) next_offset ()) == NULL)
1fd5e000
CF
279 return 0;
280
f598d941
CF
281 sf.AddrFrame.Offset = (DWORD) ebp;
282 sf.AddrPC.Offset = sf.AddrReturn.Offset;
283
1fd5e000
CF
284 if (!sf.AddrPC.Offset)
285 return 0; /* stack frames are exhausted */
286
287 /* The return address always follows the stack pointer */
288 sf.AddrReturn.Offset = (DWORD) *++ebp;
289
f598d941
CF
290 if (needargs)
291 /* The arguments follow the return address */
292 for (unsigned i = 0; i < NPARAMS; i++)
293 sf.Params[i] = (DWORD) *++ebp;
294
1fd5e000
CF
295 return 1;
296}
297
8366e93b 298static void
f598d941 299stackdump (DWORD ebp, int open_file, bool isexception)
1fd5e000 300{
8abeff1e
CF
301 extern unsigned long rlim_core;
302
303 if (rlim_core == 0UL)
304 return;
305
306 if (open_file)
307 open_stackdumpfile ();
308
1fd5e000
CF
309 int i;
310
f598d941 311 thestack.init (ebp, 1, !isexception); /* Initialize from the input CONTEXT */
1fd5e000 312 small_printf ("Stack trace:\r\nFrame Function Args\r\n");
8366e93b 313 for (i = 0; i < 16 && thestack++; i++)
1fd5e000 314 {
af1dc7cc
CF
315 small_printf ("%08x %08x ", thestack.sf.AddrFrame.Offset,
316 thestack.sf.AddrPC.Offset);
1fd5e000 317 for (unsigned j = 0; j < NPARAMS; j++)
af1dc7cc 318 small_printf ("%s%08x", j == 0 ? " (" : ", ", thestack.sf.Params[j]);
1fd5e000
CF
319 small_printf (")\r\n");
320 }
321 small_printf ("End of stack trace%s",
322 i == 16 ? " (more stack frames may be present)" : "");
323}
324
325/* Temporary (?) function for external callers to get a stack dump */
326extern "C" void
1d613351 327cygwin_stackdump ()
1fd5e000
CF
328{
329 CONTEXT c;
330 c.ContextFlags = CONTEXT_FULL;
eafa31fb 331 GetThreadContext (GetCurrentThread (), &c);
f598d941 332 stackdump (c.Ebp, 0, 0);
1fd5e000
CF
333}
334
1d613351
CF
335#define TIME_TO_WAIT_FOR_DEBUGGER 10000
336
1fd5e000 337extern "C" int
8abeff1e 338try_to_debug (bool waitloop)
1fd5e000 339{
2a6fc028 340 debug_printf ("debugger_command '%s'", debugger_command);
1fd5e000
CF
341 if (*debugger_command == '\0')
342 return 0;
343
344 __small_sprintf (strchr (debugger_command, '\0'), " %u", GetCurrentProcessId ());
345
8abeff1e 346 SetThreadPriority (hMainThread, THREAD_PRIORITY_HIGHEST);
01cf5d0f 347 PROCESS_INFORMATION pi = {NULL, 0, 0, 0};
1fd5e000 348
01cf5d0f 349 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
1fd5e000
CF
350 si.lpReserved = NULL;
351 si.lpDesktop = NULL;
352 si.dwFlags = 0;
353 si.cb = sizeof (si);
354
355 /* FIXME: need to know handles of all running threads to
356 suspend_all_threads_except (current_thread_id);
357 */
358
359 /* if any of these mutexes is owned, we will fail to start any cygwin app
360 until trapped app exits */
361
1fd5e000
CF
362 ReleaseMutex (title_mutex);
363
1d613351
CF
364 /* prevent recursive exception handling */
365 char* rawenv = GetEnvironmentStrings () ;
366 for (char* p = rawenv; *p != '\0'; p = strchr (p, '\0') + 1)
367 {
368 if (strncmp (p, "CYGWIN=", sizeof ("CYGWIN=") - 1) == 0)
369 {
1d613351
CF
370 char* q = strstr (p, "error_start") ;
371 /* replace 'error_start=...' with '_rror_start=...' */
372 if (q) *q = '_' ;
373 SetEnvironmentVariable ("CYGWIN", p + sizeof ("CYGWIN=")) ;
374 break ;
375 }
376 }
377
56a42791 378 BOOL dbg;
1fd5e000
CF
379 dbg = CreateProcess (NULL,
380 debugger_command,
381 NULL,
382 NULL,
383 FALSE,
384 CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
385 NULL,
386 NULL,
387 &si,
388 &pi);
8abeff1e 389
5a64d869
CF
390 if (!dbg)
391 system_printf ("Failed to start debugger: %E");
392 else
1fd5e000 393 {
99138976 394 SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE);
8abeff1e
CF
395 if (!waitloop)
396 return 1;
918a268c 397 while (!being_debugged ())
8abeff1e 398 /* spin */;
5a64d869
CF
399 Sleep (4000);
400 small_printf ("*** continuing from debugger call\n");
1fd5e000
CF
401 }
402
8abeff1e
CF
403 /* FIXME: need to know handles of all running threads to
404 resume_all_threads_except (current_thread_id);
405 */
406 return 0;
1fd5e000
CF
407}
408
409/* Main exception handler. */
410
411static int
9cec3d45 412handle_exceptions (EXCEPTION_RECORD *e, void *, CONTEXT *in, void *)
1fd5e000
CF
413{
414 int sig;
8abeff1e
CF
415 static int NO_COPY debugging = 0;
416 static int NO_COPY recursed = 0;
417
52cd2f88 418 if (debugging && ++debugging < 500000)
11ba5ef4
CF
419 {
420 SetThreadPriority (hMainThread, THREAD_PRIORITY_NORMAL);
421 return 0;
422 }
1fd5e000
CF
423
424 /* If we've already exited, don't do anything here. Returning 1
425 tells Windows to keep looking for an exception handler. */
426 if (exit_already)
427 return 1;
428
429 /* Coerce win32 value to posix value. */
430 switch (e->ExceptionCode)
431 {
432 case STATUS_FLOAT_DENORMAL_OPERAND:
433 case STATUS_FLOAT_DIVIDE_BY_ZERO:
434 case STATUS_FLOAT_INEXACT_RESULT:
435 case STATUS_FLOAT_INVALID_OPERATION:
436 case STATUS_FLOAT_OVERFLOW:
437 case STATUS_FLOAT_STACK_CHECK:
438 case STATUS_FLOAT_UNDERFLOW:
439 case STATUS_INTEGER_DIVIDE_BY_ZERO:
440 case STATUS_INTEGER_OVERFLOW:
441 sig = SIGFPE;
442 break;
443
444 case STATUS_ILLEGAL_INSTRUCTION:
445 case STATUS_PRIVILEGED_INSTRUCTION:
446 case STATUS_NONCONTINUABLE_EXCEPTION:
447 sig = SIGILL;
448 break;
449
450 case STATUS_TIMEOUT:
451 sig = SIGALRM;
452 break;
453
454 case STATUS_ACCESS_VIOLATION:
455 case STATUS_DATATYPE_MISALIGNMENT:
456 case STATUS_ARRAY_BOUNDS_EXCEEDED:
457 case STATUS_GUARD_PAGE_VIOLATION:
458 case STATUS_IN_PAGE_ERROR:
459 case STATUS_NO_MEMORY:
460 case STATUS_INVALID_DISPOSITION:
461 case STATUS_STACK_OVERFLOW:
462 sig = SIGSEGV;
463 break;
464
465 case STATUS_CONTROL_C_EXIT:
466 sig = SIGINT;
467 break;
468
469 case STATUS_INVALID_HANDLE:
470 /* CloseHandle will throw this exception if it is given an
471 invalid handle. We don't care about the exception; we just
472 want CloseHandle to return an error. This can be revisited
473 if gcc ever supports Windows style structured exception
474 handling. */
475 return 0;
476
477 default:
478 /* If we don't recognize the exception, we have to assume that
479 we are doing structured exception handling, and we let
480 something else handle it. */
481 return 1;
482 }
483
484 debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
485 debug_printf ("In cygwin_except_handler sig = %d at %p", sig, in->Eip);
486
1d613351
CF
487 if (myself->getsig (sig).sa_mask & SIGTOMASK (sig))
488 syscall_printf ("signal %d, masked %p", sig, myself->getsig (sig).sa_mask);
1fd5e000 489
8366e93b 490 debug_printf ("In cygwin_except_handler calling %p",
1d613351 491 myself->getsig (sig).sa_handler);
8366e93b
CF
492
493 DWORD *ebp = (DWORD *)in->Esp;
494 for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--)
495 if (*ebp == in->SegCs && ebp[-1] == in->Eip)
496 {
497 ebp -= 2;
498 break;
499 }
500
1fd5e000 501 if (!myself->progname[0]
f9f2ed0e 502 || GetCurrentThreadId () == sigtid
1d613351
CF
503 || (void *) myself->getsig (sig).sa_handler == (void *) SIG_DFL
504 || (void *) myself->getsig (sig).sa_handler == (void *) SIG_IGN
505 || (void *) myself->getsig (sig).sa_handler == (void *) SIG_ERR)
1fd5e000 506 {
1fd5e000
CF
507 /* Print the exception to the console */
508 if (e)
509 {
510 for (int i = 0; status_info[i].name; i++)
511 {
512 if (status_info[i].code == e->ExceptionCode)
513 {
5bba0cb5
CF
514 if (!myself->ppid_handle)
515 system_printf ("Exception: %s", status_info[i].name);
1fd5e000
CF
516 break;
517 }
518 }
519 }
520
521 /* Another exception could happen while tracing or while exiting.
522 Only do this once. */
8abeff1e 523 if (recursed++)
1d613351 524 system_printf ("Error while dumping state (probably corrupted stack)");
1fd5e000
CF
525 else
526 {
8abeff1e
CF
527 if (try_to_debug (0))
528 {
529 debugging = 1;
530 return 0;
531 }
532
533 open_stackdumpfile ();
534 exception (e, in);
f598d941 535 stackdump ((DWORD) ebp, 0, 1);
1fd5e000 536 }
8abeff1e
CF
537
538 signal_exit (0x80 | sig); // Flag signal + core dump
1fd5e000
CF
539 }
540
cba63823 541 sig_send (NULL, sig, (DWORD) ebp, 1); // Signal myself
1fd5e000
CF
542 return 0;
543}
544#endif /* __i386__ */
545
546#ifndef HAVE_STACK_TRACE
547void
548stack (void)
549{
550 system_printf ("Stack trace not yet supported on this machine.");
551}
552#endif
1fd5e000
CF
553
554/* Utilities to call a user supplied exception handler. */
555
077ec4cb 556#define SIG_NONMASKABLE (SIGTOMASK (SIGKILL) | SIGTOMASK (SIGSTOP))
1fd5e000
CF
557
558#ifdef __i386__
559#define HAVE_CALL_HANDLER
560
561/* Non-raceable sigsuspend
562 * Note: This implementation is based on the Single UNIX Specification
563 * man page. This indicates that sigsuspend always returns -1 and that
564 * attempts to block unblockable signals will be silently ignored.
565 * This is counter to what appears to be documented in some UNIX
566 * man pages, e.g. Linux.
567 */
568int __stdcall
569handle_sigsuspend (sigset_t tempmask)
570{
70a11195 571 sigframe thisframe (mainthread);
1fd5e000
CF
572 sigset_t oldmask = myself->getsigmask (); // Remember for restoration
573
574 set_process_mask (tempmask & ~SIG_NONMASKABLE);// Let signals we're
575 // interested in through.
576 sigproc_printf ("old mask %x, new mask %x", oldmask, tempmask);
577
1fd5e000
CF
578 WaitForSingleObject (signal_arrived, INFINITE);
579
580 set_sig_errno (EINTR); // Per POSIX
581
582 /* A signal dispatch function will have been added to our stack and will
583 be hit eventually. Set the old mask to be restored when the signal
584 handler returns. */
585
586 sigsave.oldmask = oldmask; // Will be restored by signal handler
587 return -1;
588}
589
590extern DWORD exec_exit; // Possible exit value for exec
591extern int pending_signals;
592
a7cde2b9
CF
593extern "C" {
594static void
595sig_handle_tty_stop (int sig)
596{
903c330d
CF
597 /* Silently ignore attempts to suspend if there is no accomodating
598 cygwin parent to deal with this behavior. */
599 if (!myself->ppid_handle)
99a5bd2f
CF
600 {
601 myself->process_state &= ~PID_STOPPED;
602 return;
603 }
9e73b339 604
a7cde2b9
CF
605 myself->stopsig = sig;
606 /* See if we have a living parent. If so, send it a special signal.
607 * It will figure out exactly which pid has stopped by scanning
608 * its list of subprocesses.
609 */
610 if (my_parent_is_alive ())
611 {
612 pinfo parent (myself->ppid);
9e73b339
CF
613 if (!(parent->getsig (SIGCHLD).sa_flags & SA_NOCLDSTOP))
614 sig_send (parent, SIGCHLD);
a7cde2b9
CF
615 }
616 sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
617 myself->pid, sig, myself->ppid_handle);
0428827b
CF
618 if (WaitForSingleObject (sigCONT, INFINITE) != WAIT_OBJECT_0)
619 api_fatal ("WaitSingleObject failed, %E");
620 (void) ResetEvent (sigCONT);
a7cde2b9
CF
621 return;
622}
623}
624
f02f1f14 625int
6cb613a4 626interruptible (DWORD pc, int testvalid = 0)
1fd5e000 627{
0cda2f46 628 int res;
e2fa5023
CF
629 MEMORY_BASIC_INFORMATION m;
630
631 memset (&m, 0, sizeof m);
632 if (!VirtualQuery ((LPCVOID) pc, &m, sizeof m))
633 sigproc_printf ("couldn't get memory info, pc %p, %E", pc);
634
635 char *checkdir = (char *) alloca (windows_system_directory_length + 4);
636 memset (checkdir, 0, sizeof (checkdir));
637
638# define h ((HMODULE) m.AllocationBase)
639 /* Apparently Windows 95 can sometimes return bogus addresses from
640 GetThreadContext. These resolve to an allocation base == 0.
641 These should *never* be treated as interruptible. */
642 if (!h || m.State != MEM_COMMIT)
643 res = 0;
644 else if (testvalid)
645 res = 1; /* All we wanted to know was if this was a valid module. */
646 else if (h == user_data->hmodule)
647 res = 1;
648 else if (h == cygwin_hmodule)
649 res = 0;
650 else if (!GetModuleFileName (h, checkdir, windows_system_directory_length + 2))
8656ee07
CF
651 res = 0;
652 else
e2fa5023
CF
653 res = !strncasematch (windows_system_directory, checkdir,
654 windows_system_directory_length);
7a4078ee 655 sigproc_printf ("pc %p, h %p, interruptible %d, testvalid %d", pc, h, res, testvalid);
e2fa5023 656# undef h
8656ee07 657 return res;
1fd5e000
CF
658}
659
efd76e41
CF
660bool
661sigthread::get_winapi_lock (int test)
662{
663 if (test)
63b61cd1 664 return !InterlockedExchange (&winapi_lock, 1);
efd76e41
CF
665
666 /* Need to do a busy loop because we can't block or a potential SuspendThread
667 will hang. */
63b61cd1 668 while (InterlockedExchange (&winapi_lock, 1))
efd76e41
CF
669 Sleep (1);
670 return 1;
671}
672
673void
674sigthread::release_winapi_lock ()
675{
676 /* Assumes that we have the lock. */
63b61cd1 677 InterlockedExchange (&winapi_lock, 0);
efd76e41
CF
678}
679
2803e941
CF
680static void __stdcall interrupt_setup (int sig, void *handler, DWORD retaddr,
681 DWORD *retaddr_on_stack,
682 struct sigaction& siga)
683 __attribute__((regparm(3)));
d542443e 684static void __stdcall
2803e941
CF
685interrupt_setup (int sig, void *handler, DWORD retaddr, DWORD *retaddr_on_stack,
686 struct sigaction& siga)
1fd5e000 687{
d542443e 688 sigsave.retaddr = retaddr;
0cda2f46 689 sigsave.retaddr_on_stack = retaddr_on_stack;
d542443e 690 /* FIXME: Not multi-thread aware */
775275aa
CF
691 sigsave.oldmask = myself->getsigmask ();
692 sigsave.newmask = sigsave.oldmask | siga.sa_mask | SIGTOMASK (sig);
c3d62298 693 sigsave.sa_flags = siga.sa_flags;
d542443e
CF
694 sigsave.func = (void (*)(int)) handler;
695 sigsave.sig = sig;
696 sigsave.saved_errno = -1; // Flag: no errno to save
a7cde2b9
CF
697 if (handler == sig_handle_tty_stop)
698 {
699 myself->stopsig = 0;
700 myself->process_state |= PID_STOPPED;
701 }
12520587
CF
702 /* Clear any waiting threads prior to dispatching to handler function */
703 proc_subproc (PROC_CLEARWAIT, 1);
704 int res = SetEvent (signal_arrived); // For an EINTR case
705 sigproc_printf ("armed signal_arrived %p, res %d", signal_arrived, res);
d542443e 706}
1fd5e000 707
2803e941 708static bool interrupt_now (CONTEXT *, int, void *, struct sigaction&) __attribute__((regparm(3)));
dd11f11f 709static bool
2803e941 710interrupt_now (CONTEXT *ctx, int sig, void *handler, struct sigaction& siga)
d542443e 711{
2803e941 712 interrupt_setup (sig, handler, ctx->Eip, 0, siga);
d542443e 713 ctx->Eip = (DWORD) sigdelayed;
12520587 714 SetThreadContext (myself->getthread2signal (), ctx); /* Restart the thread in a new location */
dd11f11f 715 return 1;
1fd5e000
CF
716}
717
166b2571 718void __stdcall
0cda2f46
CF
719signal_fixup_after_fork ()
720{
3cb62bd6 721 if (sigsave.sig)
0cda2f46 722 {
3cb62bd6
CF
723 sigsave.sig = 0;
724 if (sigsave.retaddr_on_stack)
725 {
726 *sigsave.retaddr_on_stack = sigsave.retaddr;
727 set_process_mask (sigsave.oldmask);
728 }
0cda2f46 729 }
3cb62bd6 730 sigproc_init ();
0cda2f46 731}
1d613351 732
166b2571
CF
733void __stdcall
734signal_fixup_after_exec (bool isspawn)
735{
736 /* Set up child's signal handlers */
737 for (int i = 0; i < NSIG; i++)
738 {
c90e1cf1
CF
739 myself->getsig (i).sa_mask = 0;
740 if (myself->getsig (i).sa_handler != SIG_IGN || isspawn)
741 myself->getsig (i).sa_handler = SIG_DFL;
166b2571
CF
742 }
743}
744
2803e941 745static int interrupt_on_return (sigthread *, int, void *, struct sigaction&) __attribute__((regparm(3)));
d542443e 746static int
2803e941 747interrupt_on_return (sigthread *th, int sig, void *handler, struct sigaction& siga)
1fd5e000
CF
748{
749 int i;
dd11f11f 750 DWORD ebp = th->frame;
1fd5e000 751
dd11f11f
CF
752 if (!ebp)
753 return 0;
1fd5e000 754
f598d941 755 thestack.init (ebp, 0, 1); /* Initialize from the input CONTEXT */
af1dc7cc 756 for (i = 0; i < 32 && thestack++ ; i++)
968d91b2 757 if (th->exception || interruptible (thestack.sf.AddrReturn.Offset))
1fd5e000 758 {
af1dc7cc
CF
759 DWORD *addr_retaddr = ((DWORD *)thestack.sf.AddrFrame.Offset) + 1;
760 if (*addr_retaddr == thestack.sf.AddrReturn.Offset)
d542443e 761 {
2803e941 762 interrupt_setup (sig, handler, *addr_retaddr, addr_retaddr, siga);
d542443e
CF
763 *addr_retaddr = (DWORD) sigdelayed;
764 }
55fc91b9 765 return 1;
1fd5e000
CF
766 }
767
0d675c5d 768 sigproc_printf ("couldn't find a stack frame, i %d\n", i);
55fc91b9 769 return 0;
1fd5e000
CF
770}
771
772extern "C" void __stdcall
773set_sig_errno (int e)
774{
775 set_errno (e);
776 sigsave.saved_errno = e;
164a681c 777 // sigproc_printf ("errno %d", e);
1fd5e000
CF
778}
779
206a8d88 780static int setup_handler (int, void *, struct sigaction&) __attribute__((regparm(3)));
1fd5e000 781static int
206a8d88 782setup_handler (int sig, void *handler, struct sigaction& siga)
1fd5e000 783{
af1dc7cc 784 CONTEXT cx;
dd11f11f 785 bool interrupted = 0;
af1dc7cc 786 HANDLE hth = NULL;
1fd5e000 787 int res;
c0188ae7 788 sigthread *th = NULL; // Initialization needed to shut up gcc
6201d15e 789
ac944e37
CF
790 if (sigsave.sig)
791 goto set_pending;
792
c0188ae7 793 for (int i = 0; !interrupted && i < CALL_HANDLER_RETRY; i++)
6cb613a4 794 {
c0188ae7 795 EnterCriticalSection (&mainthread.lock);
dd11f11f
CF
796 if (mainthread.frame)
797 th = &mainthread;
798 else
af1dc7cc 799 {
c0188ae7
CF
800 LeaveCriticalSection (&mainthread.lock);
801
dd11f11f 802 th = NULL;
dd11f11f
CF
803
804 hth = myself->getthread2signal ();
c0188ae7 805
dd11f11f
CF
806 /* Suspend the thread which will receive the signal. But first ensure that
807 this thread doesn't have any mutos. (FIXME: Someday we should just grab
808 all of the mutos rather than checking for them)
809 For Windows 95, we also have to ensure that the addresses returned by GetThreadContext
810 are valid.
811 If one of these conditions is not true we loop for a fixed number of times
812 since we don't want to stall the signal handler. FIXME: Will this result in
813 noticeable delays?
814 If the thread is already suspended (which can occur when a program is stopped) then
815 just queue the signal. */
dd11f11f 816
efd76e41
CF
817 if (!mainthread.get_winapi_lock (1))
818 continue;
c0188ae7
CF
819 sigproc_printf ("suspending mainthread");
820 res = SuspendThread (hth);
efd76e41
CF
821 mainthread.release_winapi_lock ();
822 if (mainthread.frame)
823 goto resume_thread; /* In case the main thread *just* set the frame */
6cb613a4 824
c0188ae7
CF
825 /* Just set pending if thread is already suspended */
826 if (res)
827 goto set_pending;
6201d15e 828
c0188ae7
CF
829 muto *m;
830 /* FIXME: Make multi-thread aware */
831 for (m = muto_start.next; m != NULL; m = m->next)
832 if (m->unstable () || m->owner () == mainthread.id)
833 {
834 sigproc_printf ("suspended thread owns a muto (%s)", m->name);
835 goto resume_thread;
836 }
9aa07a8f 837
c0188ae7
CF
838 EnterCriticalSection (&mainthread.lock);
839 if (mainthread.frame)
840 {
841 th = &mainthread;
842 goto try_to_interrupt;
dd11f11f 843 }
1d613351 844
c0188ae7 845 LeaveCriticalSection (&mainthread.lock);
8656ee07 846
c0188ae7
CF
847 cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
848 if (!GetThreadContext (hth, &cx))
849 system_printf ("couldn't get context of main thread, %E");
850 else if (!interruptible (cx.Eip, 1))
851 sigproc_printf ("suspended thread in a strange state pc %p, sp %p",
852 cx.Eip, cx.Esp);
853 else
854 goto try_to_interrupt;
855
856 resume_thread:
857 ResumeThread (hth);
858 Sleep (0);
859 continue;
af1dc7cc 860 }
8656ee07 861
c0188ae7 862 try_to_interrupt:
dd11f11f 863 if (th)
c0188ae7 864 {
2803e941 865 interrupted = interrupt_on_return (th, sig, handler, siga);
5e733918 866 LeaveCriticalSection (&th->lock);
c0188ae7 867 }
dd11f11f 868 else if (interruptible (cx.Eip))
2803e941 869 interrupted = interrupt_now (&cx, sig, handler, siga);
dd11f11f
CF
870 else
871 break;
1fd5e000
CF
872 }
873
b8c8fa17 874 set_pending:
12520587
CF
875 if (interrupted)
876 res = 1;
877 else
1fd5e000
CF
878 {
879 pending_signals = 1; /* FIXME: Probably need to be more tricky here */
880 sig_set_pending (sig);
b8c8fa17
CF
881 sig_dispatch_pending (1);
882 Sleep (0); /* Hopefully, other process will be waking up soon. */
dd11f11f 883 sigproc_printf ("couldn't send signal %d", sig);
1fd5e000 884 }
d542443e 885
af1dc7cc 886 if (!hth)
7cf3b655 887 sigproc_printf ("good. Didn't suspend main thread, th %p", th);
af1dc7cc
CF
888 else
889 {
890 res = ResumeThread (hth);
891 sigproc_printf ("ResumeThread returned %d", res);
892 }
68997e88 893
d542443e 894 sigproc_printf ("returning %d", interrupted);
f02f1f14 895 return interrupted;
1fd5e000
CF
896}
897#endif /* i386 */
898
899#ifndef HAVE_CALL_HANDLER
206a8d88 900#error "Need to supply machine dependent setup_handler"
1fd5e000
CF
901#endif
902
06486d9e 903/* Keyboard interrupt handler. */
1fd5e000
CF
904static BOOL WINAPI
905ctrl_c_handler (DWORD type)
906{
907 if (type == CTRL_LOGOFF_EVENT)
908 return TRUE;
909
0cc642a5
CF
910 /* Return FALSE to prevent an "End task" dialog box from appearing
911 for each Cygwin process window that's open when the computer
912 is shut down or console window is closed. */
913 if (type == CTRL_SHUTDOWN_EVENT)
914 {
915 sig_send (NULL, SIGTERM);
916 return FALSE;
917 }
918 if (type == CTRL_CLOSE_EVENT)
1fd5e000
CF
919 {
920 sig_send (NULL, SIGHUP);
921 return FALSE;
922 }
0cc642a5 923
c0a8e8d0
CF
924 /* If we are a stub and the new process has a pinfo structure, let it
925 handle this signal. */
926 if (dwExeced && pinfo (dwExeced))
927 return TRUE;
928
929 /* We're only the process group leader when we have a valid pinfo structure.
930 If we don't have one, then the parent "stub" will handle the signal. */
d7c16d8d 931 if (!pinfo (cygwin_pid (GetCurrentProcessId ())))
c0a8e8d0
CF
932 return TRUE;
933
1d613351 934 tty_min *t = cygwin_shared->tty.get_tty (myself->ctty);
c0a8e8d0 935 /* Ignore this if we're not the process group leader since it should be handled
1fd5e000 936 *by* the process group leader. */
d72a6559
CF
937 if (myself->ctty != -1 && t->getpgid () == myself->pid &&
938 (GetTickCount () - t->last_ctrl_c) >= MIN_CTRL_C_SLOP)
1fd5e000
CF
939 /* Otherwise we just send a SIGINT to the process group and return TRUE (to indicate
940 that we have handled the signal). At this point, type should be
941 a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
942 {
943 t->last_ctrl_c = GetTickCount ();
944 kill (-myself->pid, SIGINT);
945 t->last_ctrl_c = GetTickCount ();
946 return TRUE;
947 }
c0a8e8d0 948
d72a6559 949 return TRUE;
1fd5e000
CF
950}
951
952/* Set the signal mask for this process.
0d675c5d 953 Note that some signals are unmaskable, as in UNIX. */
1fd5e000
CF
954extern "C" void __stdcall
955set_process_mask (sigset_t newmask)
956{
70a11195 957 sigframe thisframe (mainthread);
1fd5e000 958 mask_sync->acquire (INFINITE);
9aa07a8f 959 sigset_t oldmask = myself->getsigmask ();
1fd5e000
CF
960 newmask &= ~SIG_NONMASKABLE;
961 sigproc_printf ("old mask = %x, new mask = %x", myself->getsigmask (), newmask);
962 myself->setsigmask (newmask); // Set a new mask
963 mask_sync->release ();
9aa07a8f
CF
964 if (oldmask != newmask && GetCurrentThreadId () != sigtid)
965 sig_dispatch_pending ();
dd11f11f
CF
966 else
967 sigproc_printf ("not calling sig_dispatch_pending. sigtid %p current %p",
968 sigtid, GetCurrentThreadId ());
1fd5e000
CF
969 return;
970}
971
1fd5e000 972int __stdcall
06486d9e 973sig_handle (int sig, bool thisproc)
1fd5e000
CF
974{
975 int rc = 0;
976
977 sigproc_printf ("signal %d", sig);
978
1d613351 979 struct sigaction thissig = myself->getsig (sig);
1fd5e000
CF
980 void *handler = (void *) thissig.sa_handler;
981
982 myself->rusage_self.ru_nsignals++;
983
984 /* Clear pending SIGCONT on stop signals */
985 if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
986 sig_clear (SIGCONT);
987
988 if (sig == SIGKILL)
989 goto exit_sig;
990
991 if (sig == SIGSTOP)
992 goto stop;
993
994 /* FIXME: Should we still do this if SIGCONT has a handler? */
995 if (sig == SIGCONT)
996 {
0428827b 997 DWORD stopped = myself->process_state & PID_STOPPED;
1fd5e000
CF
998 myself->stopsig = 0;
999 myself->process_state &= ~PID_STOPPED;
1000 /* Clear pending stop signals */
1001 sig_clear (SIGSTOP);
1002 sig_clear (SIGTSTP);
1003 sig_clear (SIGTTIN);
1004 sig_clear (SIGTTOU);
0428827b
CF
1005 if (stopped)
1006 SetEvent (sigCONT);
1fd5e000 1007 /* process pending signals */
cffaf20b 1008 sig_dispatch_pending (1);
1fd5e000
CF
1009 }
1010
1011#if 0
1012 char sigmsg[24];
1013 __small_sprintf (sigmsg, "cygwin: signal %d\n", sig);
1014 OutputDebugString (sigmsg);
1015#endif
1016
1017 if (handler == (void *) SIG_DFL)
1018 {
fcb76c5d 1019 if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH
2402700d 1020 || sig == SIGURG || (thisproc && hExeced && sig == SIGINT))
1fd5e000
CF
1021 {
1022 sigproc_printf ("default signal %d ignored", sig);
1023 goto done;
1024 }
1025
1026 if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
1027 goto stop;
1028
1029 goto exit_sig;
1030 }
1031
1032 if (handler == (void *) SIG_IGN)
1033 {
1034 sigproc_printf ("signal %d ignored", sig);
1035 goto done;
1036 }
1037
1038 if (handler == (void *) SIG_ERR)
1039 goto exit_sig;
1040
1fd5e000
CF
1041 goto dosig;
1042
8abeff1e 1043 stop:
a7cde2b9
CF
1044 /* Eat multiple attempts to STOP */
1045 if (ISSTATE (myself, PID_STOPPED))
1046 goto done;
1fd5e000 1047 handler = (void *) sig_handle_tty_stop;
c3d62298 1048 thissig = myself->getsig (SIGSTOP);
1fd5e000 1049
8abeff1e 1050 dosig:
1fd5e000 1051 /* Dispatch to the appropriate function. */
a7cde2b9 1052 sigproc_printf ("signal %d, about to call %p", sig, handler);
206a8d88 1053 rc = setup_handler (sig, handler, thissig);
1fd5e000 1054
8abeff1e 1055 done:
1fd5e000
CF
1056 sigproc_printf ("returning %d", rc);
1057 return rc;
1058
8abeff1e 1059 exit_sig:
1fd5e000
CF
1060 if (sig == SIGQUIT || sig == SIGABRT)
1061 {
8366e93b
CF
1062 CONTEXT c;
1063 c.ContextFlags = CONTEXT_FULL;
1064 GetThreadContext (hMainThread, &c);
8abeff1e 1065 if (!try_to_debug ())
f598d941 1066 stackdump (c.Ebp, 1, 1);
866c04e9 1067 sig |= 0x80;
1fd5e000
CF
1068 }
1069 sigproc_printf ("signal %d, about to call do_exit", sig);
866c04e9 1070 signal_exit (sig);
1fd5e000
CF
1071 /* Never returns */
1072}
1073
1074/* Cover function to `do_exit' to handle exiting even in presence of more
866c04e9 1075 exceptions. We used to call exit, but a SIGSEGV shouldn't cause atexit
1fd5e000 1076 routines to run. */
1fd5e000 1077static void
866c04e9 1078signal_exit (int rc)
1fd5e000 1079{
866c04e9 1080 rc = EXIT_SIGNAL | (rc << 8);
1fd5e000 1081 if (exit_already++)
1dc16fc7 1082 myself->exit (rc);
1fd5e000 1083
9149d76e
CF
1084 /* We'd like to stop the main thread from executing but when we do that it
1085 causes random, inexplicable hangs. So, instead, we set up the priority
1086 of this thread really high so that it should do its thing and then exit. */
1087 (void) SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
747e5773 1088 (void) SetThreadPriority (hMainThread, THREAD_PRIORITY_IDLE);
9149d76e
CF
1089
1090 /* Unlock any main thread mutos since we're executing with prejudice. */
1091 muto *m;
1092 for (m = muto_start.next; m != NULL; m = m->next)
1093 if (m->unstable () || m->owner () == mainthread.id)
1094 m->reset ();
1095
1096 user_data->resourcelocks->Delete ();
1097 user_data->resourcelocks->Init ();
1098
4c45a897
CF
1099 if (hExeced)
1100 TerminateProcess (hExeced, rc);
1101
e2fa5023 1102 sigproc_printf ("about to call do_exit (%x)", rc);
1fd5e000
CF
1103 do_exit (rc);
1104}
1105
1fd5e000
CF
1106HANDLE NO_COPY title_mutex = NULL;
1107
1108void
1109events_init (void)
1110{
1fd5e000
CF
1111 /* title_mutex protects modification of console title. It's neccessary
1112 while finding console window handle */
1113
1114 if (!(title_mutex = CreateMutex (&sec_all_nih, FALSE,
1115 shared_name ("title_mutex", 0))))
1116 api_fatal ("can't create title mutex, %E");
1117
1118 ProtectHandle (title_mutex);
083abe54 1119 new_muto (mask_sync);
f02f1f14
CF
1120 windows_system_directory[0] = '\0';
1121 (void) GetSystemDirectory (windows_system_directory, sizeof (windows_system_directory) - 2);
1122 char *end = strchr (windows_system_directory, '\0');
1123 if (end == windows_system_directory)
1124 api_fatal ("can't find windows system directory");
1125 if (end[-1] != '\\')
1126 {
1127 *end++ = '\\';
1128 *end = '\0';
1129 }
1130 windows_system_directory_length = end - windows_system_directory;
68997e88
CF
1131 debug_printf ("windows_system_directory '%s', windows_system_directory_length %d",
1132 windows_system_directory, windows_system_directory_length);
1133 debug_printf ("cygwin_hmodule %p", cygwin_hmodule);
1fd5e000
CF
1134}
1135
1136void
1137events_terminate (void)
1138{
1fd5e000
CF
1139 ForceCloseHandle (title_mutex);
1140 exit_already = 1;
1141}
1142
2a1743c7 1143extern "C" {
1ba3935d
CF
1144static int __stdcall
1145call_signal_handler_now ()
1146{
aed6988a
CF
1147 if (!sigsave.sig)
1148 {
1149 sigproc_printf ("call_signal_handler_now called when no signal active");
1150 return 0;
1151 }
1152
1ba3935d
CF
1153 int sa_flags = sigsave.sa_flags;
1154 sigproc_printf ("sa_flags %p", sa_flags);
1155 *sigsave.retaddr_on_stack = sigsave.retaddr;
1156 sigdelayed0 ();
1157 return sa_flags & SA_RESTART;
1158}
aa970c61
CF
1159/* This kludge seems to keep a copy of call_signal_handler_now around
1160 even when compiling with -finline-functions. */
1161static int __stdcall call_signal_handler_now_dummy ()
1162 __attribute__((alias ("call_signal_handler_now")));
2a1743c7
CF
1163};
1164
1165int
1166sigframe::call_signal_handler ()
1167{
101f820d
CF
1168 return unregister () ? call_signal_handler_now () : 0;
1169
2a1743c7
CF
1170}
1171
84c7d409 1172#define pid_offset (unsigned)(((_pinfo *)NULL)->pid)
1fd5e000 1173extern "C" {
7d72d04c 1174void __stdcall
8656ee07
CF
1175reset_signal_arrived ()
1176{
1177 (void) ResetEvent (signal_arrived);
1178 sigproc_printf ("reset signal_arrived");
1179}
1180
1d613351 1181void unused_sig_wrapper ()
1fd5e000
CF
1182{
1183/* Signal cleanup stuff. Cleans up stack (too bad that we didn't
1184 prototype signal handlers as __stdcall), calls _set_process_mask
0826bed5
CF
1185 to restore any mask, restores any potentially clobbered registers
1186 and returns to original caller. */
2116a175 1187__asm__ volatile ("\n\
12520587
CF
1188 .text \n\
1189_sigreturn: \n\
1190 addl $4,%%esp # Remove argument \n\
1191 movl %%esp,%%ebp \n\
1192 addl $36,%%ebp \n\
1193 call _set_process_mask@4 \n\
1194 \n\
1195 cmpl $0,%4 # Did a signal come in? \n\
1196 jz 1f # No, if zero \n\
1197 call _call_signal_handler_now@0 # yes handle the signal \n\
1198 \n\
11991: popl %%eax # saved errno \n\
1200 testl %%eax,%%eax # Is it < 0 \n\
1201 jl 2f # yup. ignore it \n\
1202 movl %1,%%ebx \n\
1203 movl %%eax,(%%ebx) \n\
12042: popl %%eax \n\
1205 popl %%ebx \n\
1206 popl %%ecx \n\
1207 popl %%edx \n\
1208 popl %%edi \n\
1209 popl %%esi \n\
1210 popf \n\
1211 popl %%ebp \n\
1212 ret \n\
1213 \n\
1214__no_sig_start: \n\
1215_sigdelayed: \n\
1216 pushl %2 # original return address \n\
1217_sigdelayed0: \n\
1218 pushl %%ebp \n\
1219 movl %%esp,%%ebp \n\
1220 pushf \n\
1221 pushl %%esi \n\
1222 pushl %%edi \n\
1223 pushl %%edx \n\
1224 pushl %%ecx \n\
1225 pushl %%ebx \n\
1226 pushl %%eax \n\
907dc7d0 1227 pushl %6 # saved errno \n\
12520587
CF
1228 pushl %3 # oldmask \n\
1229 pushl %4 # signal argument \n\
1230 pushl $_sigreturn \n\
1231 \n\
1232 call _reset_signal_arrived@0 \n\
1233 pushl %5 # signal number \n\
907dc7d0 1234 pushl %7 # newmask \n\
12520587 1235 movl $0,%0 # zero the signal number as a \n\
2116a175
CF
1236 # flag to the signal handler thread\n\
1237 # that it is ok to set up sigsave\n\
12520587
CF
1238 \n\
1239 call _set_process_mask@4 \n\
1240 popl %%eax \n\
1241 jmp *%%eax \n\
1242__no_sig_end: \n\
1fd5e000
CF
1243" : "=m" (sigsave.sig) : "m" (&_impure_ptr->_errno),
1244 "g" (sigsave.retaddr), "g" (sigsave.oldmask), "g" (sigsave.sig),
907dc7d0 1245 "g" (sigsave.func), "g" (sigsave.saved_errno), "g" (sigsave.newmask)
1d613351 1246);
1fd5e000
CF
1247}
1248}
This page took 0.28617 seconds and 5 git commands to generate.