diff options
author | cvs2svn <> | 2012-08-10 13:37:36 +0400 |
---|---|---|
committer | cvs2svn <> | 2012-08-10 13:37:36 +0400 |
commit | 3ed248bcc06cf81618ac20d4975f836973f9f5c0 (patch) | |
tree | b639b9e4bcdc014f46963f47b336157ff67431c8 /winsup/cygwin/exceptions.cc | |
parent | c0956742a74d194b9c18c7a91aa6d6010beb4cd3 (diff) |
This commit was manufactured by cvs2svn to create tag 'cygwin-cygwin-1_7_12-release
1_7_12-release'.
Sprout from cygwin-64bit-branch 2012-08-10 09:37:33 UTC cvs2svn 'This commit was manufactured by cvs2svn to create branch 'cygwin-64bit-'
Cherrypick from master 2012-04-03 07:28:48 UTC Corinna Vinschen <corinna@vinschen.de> ' * syscalls.cc (fhandler_base::stat_fixup): Replace string comparison':
COPYING3
COPYING3.LIB
ChangeLog
MAINTAINERS
compile
config.rpath
config.sub
config/ChangeLog
config/mh-darwin
config/mh-interix
config/mh-ppc-aix
config/mt-alphaieee
config/mt-sde
config/picflag.m4
config/stdint.m4
config/tcl.m4
configure
configure.ac
include/ChangeLog
include/bfdlink.h
include/dis-asm.h
include/dwarf2.h
include/elf/ChangeLog
include/elf/avr.h
include/elf/common.h
include/elf/m68hc11.h
include/elf/ppc.h
include/elf/s390.h
include/elf/sparc.h
include/filenames.h
include/gdb/ChangeLog
include/gdb/callback.h
include/gdb/signals.def
include/gdb/signals.h
include/mach-o/ChangeLog
include/mach-o/codesign.h
include/mach-o/external.h
include/mach-o/loader.h
include/mach-o/reloc.h
include/mach-o/x86-64.h
include/opcode/ChangeLog
include/opcode/avr.h
include/opcode/m68hc11.h
include/opcode/mips.h
include/opcode/ppc.h
include/opcode/sparc.h
include/plugin-api.h
include/splay-tree.h
ltgcc.m4
ltoptions.m4
ltversion.m4
lt~obsolete.m4
newlib/ChangeLog
newlib/doc/Makefile.am
newlib/doc/Makefile.in
newlib/libc/include/stdio.h
newlib/libc/include/string.h
newlib/libc/include/sys/signal.h
newlib/libc/include/sys/stat.h
newlib/libc/include/sys/time.h
newlib/libc/include/sys/times.h
newlib/libc/include/sys/types.h
newlib/libc/include/sys/unistd.h
newlib/libc/include/sys/wait.h
newlib/libc/locale/lmessages.c
newlib/libc/locale/lmonetary.c
newlib/libc/locale/nl_langinfo.c
newlib/libc/machine/cr16/sys/asm.h
newlib/libc/machine/epiphany/Makefile.am
newlib/libc/machine/epiphany/Makefile.in
newlib/libc/machine/epiphany/aclocal.m4
newlib/libc/machine/epiphany/configure
newlib/libc/machine/epiphany/configure.in
newlib/libc/machine/epiphany/machine/stdlib.h
newlib/libc/machine/epiphany/setjmp.S
newlib/libc/machine/rl78/Makefile.am
newlib/libc/machine/rl78/Makefile.in
newlib/libc/machine/rl78/aclocal.m4
newlib/libc/machine/rl78/configure
newlib/libc/machine/rl78/configure.in
newlib/libc/machine/rl78/setjmp.S
newlib/libc/posix/collate.c
newlib/libc/posix/engine.c
newlib/libc/posix/glob.c
newlib/libc/posix/popen.c
newlib/libc/posix/readdir.c
newlib/libc/posix/regcomp.c
newlib/libc/posix/telldir.c
newlib/libc/posix/wordexp.c
newlib/libc/reent/mkdirr.c
newlib/libc/reent/renamer.c
newlib/libc/search/hash.c
newlib/libc/search/hash_bigkey.c
newlib/libc/search/hash_page.c
newlib/libc/search/hcreate_r.c
newlib/libc/stdio/asiprintf.c
newlib/libc/stdio/asprintf.c
newlib/libc/stdio/clearerr.c
newlib/libc/stdio/fclose.c
newlib/libc/stdio/fdopen.c
newlib/libc/stdio/feof.c
newlib/libc/stdio/ferror.c
newlib/libc/stdio/fflush.c
newlib/libc/stdio/fgetc.c
newlib/libc/stdio/fgets.c
newlib/libc/stdio/fgetwc.c
newlib/libc/stdio/fgetws.c
newlib/libc/stdio/fileno.c
newlib/libc/stdio/findfp.c
newlib/libc/stdio/fmemopen.c
newlib/libc/stdio/fopen.c
newlib/libc/stdio/fopencookie.c
newlib/libc/stdio/fpurge.c
newlib/libc/stdio/fputc.c
newlib/libc/stdio/fputs.c
newlib/libc/stdio/fputwc.c
newlib/libc/stdio/fputws.c
newlib/libc/stdio/fread.c
newlib/libc/stdio/freopen.c
newlib/libc/stdio/fseek.c
newlib/libc/stdio/ftell.c
newlib/libc/stdio/funopen.c
newlib/libc/stdio/fwide.c
newlib/libc/stdio/fwrite.c
newlib/libc/stdio/getc.c
newlib/libc/stdio/getdelim.c
newlib/libc/stdio/gets.c
newlib/libc/stdio/local.h
newlib/libc/stdio/mktemp.c
newlib/libc/stdio/open_memstream.c
newlib/libc/stdio/putc.c
newlib/libc/stdio/setvbuf.c
newlib/libc/stdio/ungetc.c
newlib/libc/stdio/ungetwc.c
newlib/libc/stdio/vasiprintf.c
newlib/libc/stdio/vasprintf.c
newlib/libc/stdio/vfprintf.c
newlib/libc/stdio/vfscanf.c
newlib/libc/stdio/vfwprintf.c
newlib/libc/stdio/vfwscanf.c
newlib/libc/stdio64/fdopen64.c
newlib/libc/stdio64/fopen64.c
newlib/libc/stdio64/freopen64.c
newlib/libc/stdio64/fseeko64.c
newlib/libc/stdio64/ftello64.c
newlib/libc/stdlib/mbtowc_r.c
newlib/libc/stdlib/mprec.h
newlib/libc/stdlib/wctomb_r.c
newlib/libc/string/Makefile.am
newlib/libc/string/Makefile.in
newlib/libc/string/strcasestr.c
newlib/libc/sys/epiphany/Makefile.am
newlib/libc/sys/epiphany/Makefile.in
newlib/libc/sys/epiphany/aclocal.m4
newlib/libc/sys/epiphany/configure
newlib/libc/sys/epiphany/configure.in
newlib/libc/sys/epiphany/e_printf.c
newlib/libc/sys/rtems/crt0.c
newlib/libc/sys/rtems/machine/_types.h
newlib/libc/sys/sysnecv850/crt0.S
newlib/libc/time/strptime.c
newlib/libm/common/sf_round.c
newlib/libm/math/e_atan2.c
newlib/libm/math/e_exp.c
newlib/libm/math/e_pow.c
newlib/libm/math/e_rem_pio2.c
newlib/libm/math/ef_exp.c
newlib/libm/math/ef_pow.c
newlib/libm/math/er_lgamma.c
newlib/libm/math/erf_lgamma.c
newlib/testsuite/newlib.stdio/stdio.exp
newlib/testsuite/newlib.stdio/swprintf.c
newlib/testsuite/newlib.string/strcmp-1.c
winsup/ChangeLog
winsup/Makefile.common
winsup/cygserver/ChangeLog
winsup/cygserver/woutsup.h
winsup/cygwin/ChangeLog
winsup/cygwin/Makefile.in
winsup/cygwin/advapi32.cc
winsup/cygwin/child_info.h
winsup/cygwin/configure.in
winsup/cygwin/cygheap.cc
winsup/cygwin/cygheap.h
winsup/cygwin/cygserver_ipc.h
winsup/cygwin/cygthread.cc
winsup/cygwin/cygtls.cc
winsup/cygwin/cygtls.h
winsup/cygwin/cygwin.din
winsup/cygwin/cygwin.sc
winsup/cygwin/dcrt0.cc
winsup/cygwin/devices.cc
winsup/cygwin/devices.in
winsup/cygwin/dll_init.cc
winsup/cygwin/dtable.cc
winsup/cygwin/dtable.h
winsup/cygwin/environ.cc
winsup/cygwin/exceptions.cc
winsup/cygwin/external.cc
winsup/cygwin/fenv.cc
winsup/cygwin/fhandler.cc
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_clipboard.cc
winsup/cygwin/fhandler_console.cc
winsup/cygwin/fhandler_disk_file.cc
winsup/cygwin/fhandler_dsp.cc
winsup/cygwin/fhandler_fifo.cc
winsup/cygwin/fhandler_mem.cc
winsup/cygwin/fhandler_nodevice.cc
winsup/cygwin/fhandler_procnet.cc
winsup/cygwin/fhandler_registry.cc
winsup/cygwin/fhandler_serial.cc
winsup/cygwin/fhandler_socket.cc
winsup/cygwin/fhandler_tape.cc
winsup/cygwin/fhandler_termios.cc
winsup/cygwin/fhandler_tty.cc
winsup/cygwin/fhandler_virtual.cc
winsup/cygwin/fhandler_windows.cc
winsup/cygwin/flock.cc
winsup/cygwin/fork.cc
winsup/cygwin/gendef
winsup/cygwin/gentls_offsets
winsup/cygwin/globals.cc
winsup/cygwin/heap.cc
winsup/cygwin/hookapi.cc
winsup/cygwin/include/cygwin/if.h
winsup/cygwin/include/cygwin/in.h
winsup/cygwin/include/cygwin/socket.h
winsup/cygwin/include/cygwin/version.h
winsup/cygwin/include/elf.h
winsup/cygwin/include/inttypes.h
winsup/cygwin/include/mntent.h
winsup/cygwin/include/netdb.h
winsup/cygwin/include/stdint.h
winsup/cygwin/include/sys/elf32.h
winsup/cygwin/include/sys/elf64.h
winsup/cygwin/include/sys/elf_common.h
winsup/cygwin/include/sys/elf_generic.h
winsup/cygwin/include/sys/wait.h
winsup/cygwin/kernel32.cc
winsup/cygwin/lib/_cygwin_crt0_common.cc
winsup/cygwin/lib/crt0.h
winsup/cygwin/libc/inet_addr.c
winsup/cygwin/libc/inet_network.c
winsup/cygwin/libc/minires-os-if.c
winsup/cygwin/libc/minires.h
winsup/cygwin/libc/rcmd.cc
winsup/cygwin/miscfuncs.cc
winsup/cygwin/miscfuncs.h
winsup/cygwin/mkvers.sh
winsup/cygwin/mmap.cc
winsup/cygwin/mount.cc
winsup/cygwin/mount.h
winsup/cygwin/net.cc
winsup/cygwin/ntdll.h
winsup/cygwin/passwd.cc
winsup/cygwin/path.cc
winsup/cygwin/path.h
winsup/cygwin/pinfo.cc
winsup/cygwin/pipe.cc
winsup/cygwin/poll.cc
winsup/cygwin/posix.sgml
winsup/cygwin/posix_ipc.cc
winsup/cygwin/pseudo-reloc.cc
winsup/cygwin/regex/regcomp.c
winsup/cygwin/registry.cc
winsup/cygwin/release/1.7.10
winsup/cygwin/release/1.7.11
winsup/cygwin/release/1.7.12
winsup/cygwin/sched.cc
winsup/cygwin/sec_helper.cc
winsup/cygwin/security.cc
winsup/cygwin/security.h
winsup/cygwin/select.cc
winsup/cygwin/select.h
winsup/cygwin/shared.cc
winsup/cygwin/signal.cc
winsup/cygwin/sigproc.cc
winsup/cygwin/sigproc.h
winsup/cygwin/smallprint.cc
winsup/cygwin/spawn.cc
winsup/cygwin/strace.cc
winsup/cygwin/strfuncs.cc
winsup/cygwin/syscalls.cc
winsup/cygwin/syslog.cc
winsup/cygwin/thread.cc
winsup/cygwin/thread.h
winsup/cygwin/tlsoffsets.h
winsup/cygwin/wait.cc
winsup/cygwin/winbase.h
winsup/cygwin/wincap.cc
winsup/cygwin/wincap.h
winsup/cygwin/winlean.h
winsup/cygwin/winsup.h
winsup/doc/ChangeLog
winsup/doc/configure
winsup/doc/cygwinenv.sgml
winsup/doc/faq-programming.xml
winsup/doc/faq-using.xml
winsup/doc/new-features.sgml
winsup/doc/overview2.sgml
winsup/doc/pathnames.sgml
winsup/doc/setup-net.sgml
winsup/doc/using.sgml
winsup/lsaauth/ChangeLog
winsup/lsaauth/Makefile.in
winsup/lsaauth/cyglsa.c
winsup/lsaauth/cyglsa64.dll
winsup/lsaauth/make-64bit-version-with-mingw-w64.sh
winsup/mingw/ChangeLog
winsup/mingw/configure
winsup/mingw/configure.in
winsup/mingw/include/_mingw.h
winsup/mingw/include/excpt.h
winsup/mingw/include/inttypes.h
winsup/mingw/include/limits.h
winsup/mingw/include/process.h
winsup/mingw/include/stdint.h
winsup/mingw/include/stdio.h
winsup/mingw/include/stdlib.h
winsup/mingw/include/sys/param.h
winsup/mingw/include/wchar.h
winsup/mingw/mingwex/Makefile.in
winsup/mingw/mingwex/gdtoa/gd_qnan.h
winsup/mingw/mingwex/tsearch.c
winsup/mingw/profile/Makefile.in
winsup/testsuite/ChangeLog
winsup/testsuite/configure
winsup/utils/ChangeLog
winsup/utils/Makefile.in
winsup/utils/bloda.cc
winsup/utils/cygcheck.cc
winsup/utils/cygpath.cc
winsup/utils/dump_setup.cc
winsup/utils/dumper.cc
winsup/utils/locale.cc
winsup/utils/mkgroup.c
winsup/utils/mkpasswd.c
winsup/utils/ps.cc
winsup/utils/regtool.cc
winsup/utils/strace.cc
winsup/w32api/ChangeLog
winsup/w32api/include/setupapi.h
winsup/w32api/include/winbase.h
winsup/w32api/include/windows.h
winsup/w32api/include/winnt.h
winsup/w32api/include/winsock.h
winsup/w32api/include/winsock2.h
winsup/w32api/include/winuser.h
winsup/w32api/include/winver.h
winsup/w32api/include/wtsapi32.h
winsup/w32api/lib/Makefile.in
winsup/w32api/lib/kernel32.def
winsup/w32api/lib/wtsapi32.def
Delete:
config/asmcfi.m4
config/math.m4
config/mmap.m4
config/weakref.m4
include/dwarf2.def
include/elf/xgate.h
include/gdb/gdb-index.h
include/leb128.h
include/opcode/xgate.h
newlib/libc/string/memrchr.c
winsup/cygwin/DevNotes
winsup/cygwin/cygwait.cc
winsup/cygwin/cygwait.h
winsup/cygwin/include/machine/elf.h
winsup/cygwin/include/sys/elf.h
winsup/mingw/mingwex/membarrier.c
winsup/w32api/include/sdkddkver.h
winsup/w32api/include/shobjidl.h
winsup/w32api/lib/shobjidl-uuid.c
Diffstat (limited to 'winsup/cygwin/exceptions.cc')
-rw-r--r-- | winsup/cygwin/exceptions.cc | 248 |
1 files changed, 160 insertions, 88 deletions
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 649574fc2..458029f35 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1,7 +1,7 @@ /* exceptions.cc Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. This file is part of Cygwin. @@ -19,8 +19,8 @@ details. */ #include <syslog.h> #include <wchar.h> -#include "cygtls.h" #include "pinfo.h" +#include "cygtls.h" #include "sigproc.h" #include "shared_info.h" #include "perprocess.h" @@ -37,13 +37,16 @@ details. */ char debugger_command[2 * NT_MAX_PATH + 20]; -extern "C" void sigdelayed (); +extern "C" { +extern void sigdelayed (); +}; static BOOL WINAPI ctrl_c_handler (DWORD); /* This is set to indicate that we have already exited. */ static NO_COPY int exit_already = 0; +static muto NO_COPY mask_sync; NO_COPY static struct { @@ -445,7 +448,7 @@ try_to_debug (bool waitloop) return dbg; } -extern "C" void WINAPI RtlUnwind (void *, void *, PEXCEPTION_RECORD, void *); +extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); static void __stdcall rtl_unwind (exception_list *, PEXCEPTION_RECORD) __attribute__ ((noinline, regparm (3))); void __stdcall rtl_unwind (exception_list *frame, PEXCEPTION_RECORD e) @@ -660,7 +663,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void stackdump ((DWORD) ebp, in, e); } - if ((NTSTATUS) e->ExceptionCode == STATUS_ACCESS_VIOLATION) + if (e->ExceptionCode == STATUS_ACCESS_VIOLATION) { int error_code = 0; if (si.si_code == SEGV_ACCERR) /* Address present */ @@ -672,7 +675,8 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void klog (LOG_INFO, "%s[%d]: segfault at %08x rip %08x rsp %08x error %d", __progname, myself->pid, e->ExceptionInformation[1], in->Eip, in->Esp, - error_code); + ((in->Eip >= 0x61000000 && in->Eip < 0x61200000) + ? 0 : 4) | (e->ExceptionInformation[0] << 1)); } /* Flag signal + core dump */ @@ -706,11 +710,11 @@ handle_sigsuspend (sigset_t tempmask) { sigset_t oldmask = _my_tls.sigmask; // Remember for restoration - set_signal_mask (_my_tls.sigmask, tempmask); + set_signal_mask (tempmask, _my_tls.sigmask); sigproc_printf ("oldmask %p, newmask %p", oldmask, tempmask); pthread_testcancel (); - cancelable_wait (NULL, cw_infinite, cw_cancel | cw_cancel_self | cw_sig_eintr); + cancelable_wait (signal_arrived); set_sig_errno (EINTR); // Per POSIX @@ -733,29 +737,31 @@ sig_handle_tty_stop (int sig) /* Silently ignore attempts to suspend if there is no accommodating cygwin parent to deal with this behavior. */ if (!myself->cygstarted) - myself->process_state &= ~PID_STOPPED; - else { - myself->stopsig = sig; - myself->alert_parent (sig); - sigproc_printf ("process %d stopped by signal %d", myself->pid, sig); - /* FIXME! This does nothing to suspend anything other than the main - thread. */ - DWORD res = cancelable_wait (NULL, cw_infinite, cw_sig_eintr); - switch (res) - { - case WAIT_SIGNALED: - myself->stopsig = SIGCONT; - myself->alert_parent (SIGCONT); - break; - default: - api_fatal ("WaitSingleObject returned %d", res); - break; - } + myself->process_state &= ~PID_STOPPED; + return; + } + + myself->stopsig = sig; + myself->alert_parent (sig); + sigproc_printf ("process %d stopped by signal %d", myself->pid, sig); + HANDLE w4[2]; + w4[0] = sigCONT; + w4[1] = signal_arrived; + switch (WaitForMultipleObjects (2, w4, TRUE, INFINITE)) + { + case WAIT_OBJECT_0: + case WAIT_OBJECT_0 + 1: + myself->stopsig = SIGCONT; + myself->alert_parent (SIGCONT); + break; + default: + api_fatal ("WaitSingleObject failed, %E"); + break; } _my_tls.incyg = 0; } -} /* end extern "C" */ +} bool _cygtls::interrupt_now (CONTEXT *cx, int sig, void *handler, @@ -798,11 +804,20 @@ _cygtls::interrupt_setup (int sig, void *handler, struct sigaction& siga) this->sig = sig; // Should always be last thing set to avoid a race - if (incyg && signal_arrived) - SetEvent (signal_arrived); + if (!event) + threadkill = false; + else + { + HANDLE h = event; + event = NULL; + SetEvent (h); + } + /* Clear any waiting threads prior to dispatching to handler function */ + int res = SetEvent (signal_arrived); // For an EINTR case proc_subproc (PROC_CLEARWAIT, 1); - sigproc_printf ("armed signal_arrived %p, signal %d", signal_arrived, sig); + sigproc_printf ("armed signal_arrived %p, signal %d, res %d", signal_arrived, + sig, res); } extern "C" void __stdcall @@ -850,7 +865,7 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls) If the thread is already suspended (which can occur when a program has called SuspendThread on itself) then just queue the signal. */ - sigproc_printf ("suspending thread, tls %p, _main_tls %p", tls, _main_tls); + sigproc_printf ("suspending thread"); res = SuspendThread (hth); /* Just set pending if thread is already suspended */ if (res) @@ -865,7 +880,7 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls) interrupted = tls->interrupt_now (&cx, sig, handler, siga); tls->unlock (); - ResumeThread (hth); + res = ResumeThread (hth); if (interrupted) goto out; @@ -1006,7 +1021,7 @@ ctrl_c_handler (DWORD type) extern "C" void __stdcall set_process_mask (sigset_t newmask) { - set_signal_mask (_my_tls.sigmask, newmask); + set_signal_mask (newmask, _my_tls.sigmask); } extern "C" int @@ -1019,9 +1034,11 @@ sighold (int sig) syscall_printf ("signal %d out of range", sig); return -1; } + mask_sync.acquire (INFINITE); sigset_t mask = _my_tls.sigmask; sigaddset (&mask, sig); - set_signal_mask (_my_tls.sigmask, mask); + set_signal_mask (mask, _my_tls.sigmask); + mask_sync.release (); return 0; } @@ -1035,9 +1052,11 @@ sigrelse (int sig) syscall_printf ("signal %d out of range", sig); return -1; } + mask_sync.acquire (INFINITE); sigset_t mask = _my_tls.sigmask; sigdelset (&mask, sig); - set_signal_mask (_my_tls.sigmask, mask); + set_signal_mask (mask, _my_tls.sigmask); + mask_sync.release (); return 0; } @@ -1055,6 +1074,7 @@ sigset (int sig, _sig_func_ptr func) return (_sig_func_ptr) SIG_ERR; } + mask_sync.acquire (INFINITE); sigset_t mask = _my_tls.sigmask; /* If sig was in the signal mask return SIG_HOLD, otherwise return the previous disposition. */ @@ -1073,7 +1093,8 @@ sigset (int sig, _sig_func_ptr func) signal (sig, func); sigdelset (&mask, sig); } - set_signal_mask (_my_tls.sigmask, mask); + set_signal_mask (mask, _my_tls.sigmask); + mask_sync.release (); return prev; } @@ -1084,10 +1105,11 @@ sigignore (int sig) } /* Update the signal mask for this process and return the old mask. - Called from call_signal_handler */ + Called from sigdelayed */ extern "C" sigset_t set_process_mask_delta () { + mask_sync.acquire (INFINITE); sigset_t newmask, oldmask; if (_my_tls.deltamask & SIG_NONMASKABLE) @@ -1098,35 +1120,41 @@ set_process_mask_delta () sigproc_printf ("oldmask %p, newmask %p, deltamask %p", oldmask, newmask, _my_tls.deltamask); _my_tls.sigmask = newmask; + mask_sync.release (); return oldmask; } /* Set the signal mask for this process. Note that some signals are unmaskable, as in UNIX. */ - -void -set_signal_mask (sigset_t& setmask, sigset_t newmask) +extern "C" void __stdcall +set_signal_mask (sigset_t newmask, sigset_t& oldmask) { +#ifdef CGF + if (&_my_tls == _sig_tls) + small_printf ("********* waiting in signal thread\n"); +#endif + mask_sync.acquire (INFINITE); newmask &= ~SIG_NONMASKABLE; - sigset_t mask_bits = setmask & ~newmask; - sigproc_printf ("setmask %p, newmask %p, mask_bits %p", setmask, newmask, + sigset_t mask_bits = oldmask & ~newmask; + sigproc_printf ("oldmask %p, newmask %p, mask_bits %p", oldmask, newmask, mask_bits); - setmask = newmask; + oldmask = newmask; if (mask_bits) sig_dispatch_pending (true); + mask_sync.release (); } int __stdcall sigpacket::process () { - bool continue_now; + DWORD continue_now; struct sigaction dummy = global_sigs[SIGSTOP]; if (si.si_signo != SIGCONT) continue_now = false; else { - continue_now = ISSTATE (myself, PID_STOPPED); + continue_now = myself->process_state & PID_STOPPED; myself->stopsig = 0; myself->process_state &= ~PID_STOPPED; /* Clear pending stop signals */ @@ -1156,23 +1184,16 @@ sigpacket::process () myself->rusage_self.ru_nsignals++; - void *handler = (void *) thissig.sa_handler; - if (handler == SIG_IGN) - { - sigproc_printf ("signal %d ignored", si.si_signo); - goto done; - } - - if (have_execed) + bool masked; + void *handler; + if (!have_execed || (void *) thissig.sa_handler == (void *) SIG_IGN) + handler = (void *) thissig.sa_handler; + else if (tls) + return 1; + else handler = NULL; - if (tls) - sigproc_printf ("using tls %p", tls); - else - { - tls = cygheap->find_tls (si.si_signo); - sigproc_printf ("using tls %p", tls); - } + _cygtls *use_tls = tls ?: _main_tls; if (si.si_signo == SIGKILL) goto exit_sig; @@ -1182,12 +1203,30 @@ sigpacket::process () goto stop; } - if (sigismember (&tls->sigwait_mask, si.si_signo)) + bool insigwait_mask; + if ((masked = ISSTATE (myself, PID_STOPPED))) + insigwait_mask = false; + else if (tls) + insigwait_mask = sigismember (&tls->sigwait_mask, si.si_signo); + else if (!(tls = _cygtls::find_tls (si.si_signo))) + insigwait_mask = false; + else { - tls->sigwait_mask = 0; - goto dosig; + use_tls = tls; + insigwait_mask = true; } - if (sigismember (&tls->sigmask, si.si_signo) || ISSTATE (myself, PID_STOPPED)) + + if (insigwait_mask) + goto thread_specific; + + if (masked) + /* nothing to do */; + else if (sigismember (mask, si.si_signo)) + masked = true; + else if (tls) + masked = sigismember (&tls->sigmask, si.si_signo); + + if (masked) { sigproc_printf ("signal %d blocked", si.si_signo); rc = -1; @@ -1200,10 +1239,14 @@ sigpacket::process () if (handler == (void *) SIG_DFL) { + if (insigwait_mask) + goto thread_specific; if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH || si.si_signo == SIGURG) { - sigproc_printf ("signal %d default is currently ignore", si.si_signo); + sigproc_printf ("default signal %d ignored", si.si_signo); + if (continue_now) + SetEvent (signal_arrived); goto done; } @@ -1213,35 +1256,53 @@ sigpacket::process () goto exit_sig; } + if (handler == (void *) SIG_IGN) + { + sigproc_printf ("signal %d ignored", si.si_signo); + goto done; + } + if (handler == (void *) SIG_ERR) goto exit_sig; + use_tls->set_siginfo (this); goto dosig; stop: + /* Eat multiple attempts to STOP */ + if (ISSTATE (myself, PID_STOPPED)) + goto done; handler = (void *) sig_handle_tty_stop; thissig = dummy; dosig: - if (ISSTATE (myself, PID_STOPPED) && !continue_now) - rc = -1; /* No signals delivered if stopped */ - else - { - tls->set_siginfo (this); - /* Dispatch to the appropriate function. */ - sigproc_printf ("signal %d, signal handler %p", si.si_signo, handler); - rc = setup_handler (si.si_signo, handler, thissig, tls); - continue_now = false; - } + /* Dispatch to the appropriate function. */ + sigproc_printf ("signal %d, about to call %p", si.si_signo, handler); + rc = setup_handler (si.si_signo, handler, thissig, use_tls); done: + tls = use_tls; if (continue_now) - SetEvent (tls->signal_arrived); + SetEvent (sigCONT); sigproc_printf ("returning %d", rc); return rc; +thread_specific: + use_tls->sig = si.si_signo; + use_tls->set_siginfo (this); + use_tls->func = NULL; + sigproc_printf ("releasing sigwait for thread"); + SetEvent (use_tls->event); + goto done; + exit_sig: - tls->signal_exit (si.si_signo); /* never returns */ + use_tls->signal_exit (si.si_signo); /* never returns */ +} + +void +events_init () +{ + mask_sync.init ("mask_sync"); } void @@ -1257,16 +1318,26 @@ _cygtls::call_signal_handler () while (1) { lock (); - if (!sig) + if (sig) + pop (); + else if (this != _main_tls) { - unlock (); - break; - } + _main_tls->lock (); + if (_main_tls->sig && _main_tls->incyg) + { + paranoid_printf ("Redirecting to main_tls signal %d", _main_tls->sig); + sig = _main_tls->sig; + sa_flags = _main_tls->sa_flags; + func = _main_tls->func; + infodata = _main_tls->infodata; + _main_tls->pop (); + _main_tls->sig = 0; - /* Pop the stack if the next "return address" is sigdelayed, since - this function is doing what sigdelayed would have done anyway. */ - if (retaddr () == (__stack_t) sigdelayed) - pop (); + } + _main_tls->unlock (); + } + if (!sig) + break; debug_only_printf ("dealing with signal %d", sig); this_sa_flags = sa_flags; @@ -1276,12 +1347,12 @@ _cygtls::call_signal_handler () sigset_t this_oldmask = set_process_mask_delta (); int this_errno = saved_errno; sig = 0; - reset_signal_arrived (); unlock (); // make sure synchronized if (!(this_sa_flags & SA_SIGINFO)) { + void (*sigfunc) (int) = thisfunc; incyg = false; - thisfunc (thissig); + sigfunc (thissig); } else { @@ -1292,11 +1363,12 @@ _cygtls::call_signal_handler () sigact (thissig, &thissi, NULL); } incyg = true; - set_signal_mask (_my_tls.sigmask, this_oldmask); + set_signal_mask (this_oldmask, _my_tls.sigmask); if (this_errno >= 0) set_errno (this_errno); } + unlock (); return this_sa_flags & SA_RESTART || (this != _main_tls); } |