From 528874e24ea81be8a827b25d6446828aafd8b84e Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Thu, 15 Jan 2004 18:29:38 +0000 Subject: * gentls_offsets: Reinstate unlink of temp files. --- winsup/cygwin/ChangeLog | 4 + winsup/cygwin/cygtls.cc | 7 ++ winsup/cygwin/cygtls.h | 3 +- winsup/cygwin/dcrt0.cc | 6 +- winsup/cygwin/exceptions.cc | 157 +++++++++++++++++++++------------- winsup/cygwin/fhandler_termios.cc | 16 +++- winsup/cygwin/fhandler_tty.cc | 4 +- winsup/cygwin/gentls_offsets | 4 +- winsup/cygwin/include/cygwin/signal.h | 46 +++++----- winsup/cygwin/signal.cc | 70 ++++++++++----- winsup/cygwin/sigproc.cc | 132 ++++++++++++++-------------- winsup/cygwin/sigproc.h | 24 +++++- winsup/cygwin/thread.cc | 6 +- winsup/cygwin/winsup.h | 4 - 14 files changed, 294 insertions(+), 189 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f1e3f2f..16aa73f 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,7 @@ +2004-01-15 Christopher Faylor + + * gentls_offsets: Reinstate unlink of temp files. + 2004-01-14 Christopher Faylor * fhandler_console.cc (fhandler_console::close): Fix debugging output. diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc index 5c9fa61..ecec3f5 100644 --- a/winsup/cygwin/cygtls.cc +++ b/winsup/cygwin/cygtls.cc @@ -20,6 +20,7 @@ details. */ #include "dtable.h" #include "cygheap.h" #include "cygthread.h" +#include "sigproc.h" class sentry { @@ -189,6 +190,12 @@ _threadinfo::find_tls (int sig) return res; } +void +_threadinfo::set_siginfo (sigpacket *pack) +{ + infodata = pack->si; +} + extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); static int handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *, void *) diff --git a/winsup/cygwin/cygtls.h b/winsup/cygwin/cygtls.h index 779e42b..ab82bac 100644 --- a/winsup/cygwin/cygtls.h +++ b/winsup/cygwin/cygtls.h @@ -120,7 +120,7 @@ struct _threadinfo static void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3))); static struct _threadinfo *find_tls (int sig); void remove (DWORD); - void push (__stack_t, bool = false); + void push (__stack_t, bool = false) __attribute__ ((regparm (3))); __stack_t pop (); bool isinitialized () {return initialized == CYGTLS_INITIALIZED || initialized == CYGTLS_EXCEPTION;} void set_state (bool); @@ -131,6 +131,7 @@ struct _threadinfo __attribute__((regparm(3))); void init_threadlist_exceptions (struct _exception_list *); operator HANDLE () const {return tid->win32_obj_id;} + void set_siginfo (struct sigpacket *) __attribute__ ((regparm (3))); /*gentls_offsets*/ }; #pragma pack(pop) diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index 3d6b7a8..4b905b7 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -1042,9 +1042,13 @@ do_exit (int status) /* Kill orphaned children on group leader exit */ if (myself->has_pgid_children && myself->pid == myself->pgid) { + siginfo_t si; + si.si_signo = -SIGHUP; + si.si_code = SI_KERNEL; + si.si_pid = si.si_uid = si.si_errno = 0; sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children", myself->pid, myself->pgid); - kill_pgrp (myself->pgid, -SIGHUP); + kill_pgrp (myself->pgid, si); } } diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index 597c58e..1fea4cd 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -419,30 +419,56 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) RtlUnwind (frame, ret_here, e0, 0); __asm__ volatile (".equ _ret_here,."); - int sig; + siginfo_t si; /* Coerce win32 value to posix value. */ switch (e.ExceptionCode) { case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DIVIDE_BY_ZERO: - case STATUS_FLOAT_INEXACT_RESULT: case STATUS_FLOAT_INVALID_OPERATION: - case STATUS_FLOAT_OVERFLOW: case STATUS_FLOAT_STACK_CHECK: + si.si_signo = SIGFPE; + si.si_sigval.sival_int = FPE_FLTSUB; + break; + case STATUS_FLOAT_INEXACT_RESULT: + si.si_signo = SIGFPE; + si.si_sigval.sival_int = FPE_FLTRES; + break; + case STATUS_FLOAT_OVERFLOW: + si.si_signo = SIGFPE; + si.si_sigval.sival_int = FPE_FLTOVF; + break; case STATUS_FLOAT_UNDERFLOW: + si.si_signo = SIGFPE; + si.si_sigval.sival_int = FPE_FLTUND; + break; case STATUS_INTEGER_DIVIDE_BY_ZERO: + si.si_signo = SIGFPE; + si.si_sigval.sival_int = FPE_INTDIV; + break; case STATUS_INTEGER_OVERFLOW: - sig = SIGFPE; + si.si_signo = SIGFPE; + si.si_sigval.sival_int = FPE_INTOVF; break; case STATUS_ILLEGAL_INSTRUCTION: + si.si_signo = SIGILL; + si.si_sigval.sival_int = ILL_ILLOPC; + break; + case STATUS_PRIVILEGED_INSTRUCTION: + si.si_signo = SIGILL; + si.si_sigval.sival_int = ILL_PRVOPC; + break; + case STATUS_NONCONTINUABLE_EXCEPTION: - sig = SIGILL; + si.si_signo = SIGILL; + si.si_sigval.sival_int = ILL_ILLADR; break; case STATUS_TIMEOUT: - sig = SIGALRM; + si.si_signo = SIGALRM; + si.si_sigval.sival_int = 0; break; case STATUS_ACCESS_VIOLATION: @@ -453,11 +479,13 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) case STATUS_NO_MEMORY: case STATUS_INVALID_DISPOSITION: case STATUS_STACK_OVERFLOW: - sig = SIGSEGV; + si.si_signo = SIGSEGV; + si.si_sigval.sival_int = SEGV_MAPERR; break; case STATUS_CONTROL_C_EXIT: - sig = SIGINT; + si.si_signo = SIGINT; + si.si_sigval.sival_int = 0; break; case STATUS_INVALID_HANDLE: @@ -476,13 +504,14 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) } debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e.ExceptionCode, in.Eip, in.Esp); - debug_printf ("In cygwin_except_handler sig = %d at %p", sig, in.Eip); + debug_printf ("In cygwin_except_handler sig = %d at %p", si.si_signo, in.Eip); - if (global_sigs[sig].sa_mask & SIGTOMASK (sig)) - syscall_printf ("signal %d, masked %p", sig, global_sigs[sig].sa_mask); + if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo)) + syscall_printf ("signal %d, masked %p", si.si_signo, + global_sigs[si.si_signo].sa_mask); debug_printf ("In cygwin_except_handler calling %p", - global_sigs[sig].sa_handler); + global_sigs[si.si_signo].sa_handler); DWORD *ebp = (DWORD *)in.Esp; for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--) @@ -494,23 +523,18 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) if (!myself->progname[0] || GetCurrentThreadId () == sigtid - || (void *) global_sigs[sig].sa_handler == (void *) SIG_DFL - || (void *) global_sigs[sig].sa_handler == (void *) SIG_IGN - || (void *) global_sigs[sig].sa_handler == (void *) SIG_ERR) + || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL + || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN + || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR) { /* Print the exception to the console */ - if (1) - { - for (int i = 0; status_info[i].name; i++) - { - if (status_info[i].code == e.ExceptionCode) - { - if (!myself->ppid_handle) - system_printf ("Exception: %s", status_info[i].name); - break; - } - } - } + for (int i = 0; status_info[i].name; i++) + if (status_info[i].code == e.ExceptionCode) + { + if (!myself->ppid_handle) + system_printf ("Exception: %s", status_info[i].name); + break; + } /* Another exception could happen while tracing or while exiting. Only do this once. */ @@ -529,11 +553,13 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *) stackdump ((DWORD) ebp, 0, 1); } - signal_exit (0x80 | sig); // Flag signal + core dump + signal_exit (0x80 | si.si_signo); // Flag signal + core dump } - _my_tls.push ((__stack_t) ebp, true); - sig_send (NULL, sig, &_my_tls); // Signal myself + si.si_addr = ebp; + si.si_code = SI_KERNEL; + si.si_errno = si.si_pid = si.si_uid = 0; + sig_send (NULL, si, &_my_tls); // Signal myself return 1; } #endif /* __i386__ */ @@ -605,7 +631,14 @@ sig_handle_tty_stop (int sig) { pinfo parent (myself->ppid); if (ISSTATE (parent, PID_NOCLDSTOP)) - sig_send (parent, SIGCHLD); + { + siginfo_t si; + si.si_signo = SIGCHLD; + si.si_code = SI_KERNEL; + si.si_sigval.sival_int = CLD_STOPPED; + si.si_errno = si.si_pid = si.si_uid = si.si_errno = 0; + sig_send (parent, si); + } } sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p", myself->pid, sig, myself->ppid_handle); @@ -814,8 +847,8 @@ ctrl_c_handler (DWORD type) { if (type == CTRL_CLOSE_EVENT) { - saw_close = true; sig_send (NULL, SIGHUP); + saw_close = true; return FALSE; } if (!saw_close && type == CTRL_LOGOFF_EVENT) @@ -849,7 +882,7 @@ ctrl_c_handler (DWORD type) a CTRL_C_EVENT or CTRL_BREAK_EVENT. */ { t->last_ctrl_c = GetTickCount (); - kill (-myself->pid, SIGINT); + killsys (-myself->pid, SIGINT); t->last_ctrl_c = GetTickCount (); return TRUE; } @@ -884,9 +917,9 @@ set_signal_mask (sigset_t newmask, sigset_t oldmask) } int __stdcall -sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls) +sigpacket::process () { - if (sig == SIGCONT) + if (si.si_signo == SIGCONT) { DWORD stopped = myself->process_state & PID_STOPPED; myself->stopsig = 0; @@ -901,41 +934,44 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls) } int rc = 1; - bool insigwait_mask = tls ? sigismember (&tls->sigwait_mask, sig) : false; + bool insigwait_mask = tls ? sigismember (&tls->sigwait_mask, si.si_signo) : false; bool special_case = ISSTATE (myself, PID_STOPPED) || main_vfork->pid; - bool masked = sigismember (&mask, sig); - if (sig != SIGKILL && sig != SIGSTOP + bool masked = sigismember (mask, si.si_signo); + if (si.si_signo != SIGKILL && si.si_signo != SIGSTOP && (special_case || main_vfork->pid || masked || insigwait_mask - || (tls && sigismember (&tls->sigmask, sig)))) + || (tls && sigismember (&tls->sigmask, si.si_signo)))) { - sigproc_printf ("signal %d blocked", sig); + sigproc_printf ("signal %d blocked", si.si_signo); if ((!special_case && !masked) - && (insigwait_mask || (tls = _threadinfo::find_tls (sig)) != NULL)) + && (insigwait_mask || (tls = _threadinfo::find_tls (si.si_signo)) != NULL)) goto thread_specific; rc = -1; goto done; } /* Clear pending SIGCONT on stop signals */ - if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) + if (si.si_signo == SIGSTOP || si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU) sig_clear (SIGCONT); - sigproc_printf ("signal %d processing", sig); - struct sigaction thissig = global_sigs[sig]; + sigproc_printf ("signal %d processing", si.si_signo); + struct sigaction thissig = global_sigs[si.si_signo]; void *handler; handler = (void *) thissig.sa_handler; myself->rusage_self.ru_nsignals++; - if (sig == SIGKILL) + if (si.si_signo == SIGKILL) goto exit_sig; - if (sig == SIGSTOP) + if (!tls) + tls = _main_tls; + + if (si.si_signo == SIGSTOP) goto stop; #if 0 char sigmsg[24]; - __small_sprintf (sigmsg, "cygwin: signal %d\n", sig); + __small_sprintf (sigmsg, "cygwin: signal %d\n", si.si_signo); OutputDebugString (sigmsg); #endif @@ -943,14 +979,14 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls) { if (insigwait_mask) goto thread_specific; - if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH - || sig == SIGURG) + if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH + || si.si_signo == SIGURG) { - sigproc_printf ("default signal %d ignored", sig); + sigproc_printf ("default signal %d ignored", si.si_signo); goto done; } - if (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU) + if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU) goto stop; goto exit_sig; @@ -958,7 +994,7 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls) if (handler == (void *) SIG_IGN) { - sigproc_printf ("signal %d ignored", sig); + sigproc_printf ("signal %d ignored", si.si_signo); goto done; } @@ -973,34 +1009,37 @@ stop: goto done; handler = (void *) sig_handle_tty_stop; thissig = global_sigs[SIGSTOP]; + goto dosig1; dosig: + tls->set_siginfo (this); +dosig1: /* Dispatch to the appropriate function. */ - sigproc_printf ("signal %d, about to call %p", sig, handler); - rc = setup_handler (sig, handler, thissig, tls ?: _main_tls); + sigproc_printf ("signal %d, about to call %p", si.si_signo, handler); + rc = setup_handler (si.si_signo, handler, thissig, tls); done: sigproc_printf ("returning %d", rc); return rc; thread_specific: - tls->sig = sig; + tls->sig = si.si_signo; sigproc_printf ("releasing sigwait for thread"); SetEvent (tls->event); goto done; exit_sig: - if (sig == SIGQUIT || sig == SIGABRT) + if (si.si_signo == SIGQUIT || si.si_signo == SIGABRT) { CONTEXT c; c.ContextFlags = CONTEXT_FULL; GetThreadContext (hMainThread, &c); if (!try_to_debug ()) stackdump (c.Ebp, 1, 1); - sig |= 0x80; + si.si_signo |= 0x80; } - sigproc_printf ("signal %d, about to call do_exit", sig); - signal_exit (sig); + sigproc_printf ("signal %d, about to call do_exit", si.si_signo); + signal_exit (si.si_signo); /* Never returns */ } diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index edb8354..398dabd 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -87,6 +87,10 @@ tty_min::kill_pgrp (int sig) { int killself = 0; winpids pids ((DWORD) PID_MAP_RW); + siginfo_t si; + si.si_signo = sig; + si.si_code = SI_KERNEL; + si.si_pid = si.si_uid = si.si_errno = 0; for (unsigned i = 0; i < pids.npids; i++) { _pinfo *p = pids[i]; @@ -95,10 +99,10 @@ tty_min::kill_pgrp (int sig) if (p == myself) killself++; else - (void) sig_send (p, sig); + (void) sig_send (p, si); } if (killself) - sig_send (myself, sig); + sig_send (myself, si); } bg_check_types @@ -144,7 +148,13 @@ fhandler_termios::bg_check (int sig) /* Don't raise a SIGTT* signal if we have already been interrupted by another signal. */ if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0) - kill_pgrp (myself->pgid, sig); + { + siginfo_t si; + si.si_signo = sig; + si.si_code = SI_KERNEL; + si.si_pid = si.si_uid = si.si_errno = 0; + kill_pgrp (myself->pgid, si); + } return bg_signalled; setEIO: diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index ef308b0..33c7f37 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -1109,7 +1109,7 @@ fhandler_tty_slave::ioctl (unsigned int cmd, void *arg) get_ttyp ()->arg.winsize = *(struct winsize *) arg; SetEvent (ioctl_request_event); get_ttyp ()->winsize = *(struct winsize *) arg; - kill (-get_ttyp ()->getpgid (), SIGWINCH); + killsys (-get_ttyp ()->getpgid (), SIGWINCH); if (ioctl_done_event) WaitForSingleObject (ioctl_done_event, INFINITE); } @@ -1307,7 +1307,7 @@ fhandler_pty_master::ioctl (unsigned int cmd, void *arg) || get_ttyp ()->winsize.ws_col != ((struct winsize *) arg)->ws_col) { get_ttyp ()->winsize = *(struct winsize *) arg; - kill (-get_ttyp ()->getpgid (), SIGWINCH); + killsys (-get_ttyp ()->getpgid (), SIGWINCH); } break; case FIONBIO: diff --git a/winsup/cygwin/gentls_offsets b/winsup/cygwin/gentls_offsets index 434707b..375b668 100755 --- a/winsup/cygwin/gentls_offsets +++ b/winsup/cygwin/gentls_offsets @@ -5,7 +5,7 @@ open(TLS, $tls) or die "$0: couldn't open tls file \"$tls\" - $!\n"; my $struct = ''; my @fields = (); my $def = ''; -my $tls = join('', ); +$tls = join('', ); $tls =~ s/\n[^\n]*gentls_offsets[^\n]*\n(.+)\Z/$1/os; my $pre = $`; substr($tls, 0, length($pre)) = ''; @@ -75,5 +75,5 @@ open(OFFS, "/tmp/$$.a.out|") or die "$0: couldn't run \"/tmp/$$.a.out\" - $!\n"; print TLS_OUT ; close OFFS; close TLS_OUT; -# unlink "/tmp/$$.cc", "/tmp/$$.a.out"; +unlink "/tmp/$$.cc", "/tmp/$$.a.out"; exit(0); diff --git a/winsup/cygwin/include/cygwin/signal.h b/winsup/cygwin/include/cygwin/signal.h index 1e28634..5e26bf4 100644 --- a/winsup/cygwin/include/cygwin/signal.h +++ b/winsup/cygwin/include/cygwin/signal.h @@ -8,7 +8,7 @@ struct ucontext void *uc_link; stack_t uc_stack; struct sigcontext uc_mcontext; - sigset_t uc_sigmask; + sigset_t uc_sigmask; }; #endif @@ -22,45 +22,41 @@ typedef union sigval typedef struct { int si_signo; /* signal number */ - int si_errno; /* errno associated with signal */ int si_code; /* signal code */ + pid_t si_pid; /* sender's pid */ + uid_t si_uid; /* sender's uid */ + int si_errno; /* errno associated with signal */ union { - int __pad[128]; /* plan for future growth */ - + __uint32_t __pad[120]; /* plan for future growth */ union { - /* timers */ + /* timers */ struct { - unsigned int si_tid; /* timer id */ - unsigned int si_overrun; /* overrun count */ + union + { + struct + { + unsigned int si_tid; /* timer id */ + unsigned int si_overrun; /* overrun count */ + }; + }; + sigval_t si_sigval; /* signal value */ }; - - /* POSIX signals or signals invoked by kill() */ - struct - { - pid_t si_pid; /* sender's pid */ - uid_t si_uid; /* sender's uid */ - }; - sigval_t si_sigval; /* signal value */ }; + /* SIGCHLD */ struct { - pid_t si_pid2; /* which child */ - uid_t si_uid2; /* sender's uid */ - int si_status; /* exit code */ + int si_status; /* exit code */ clock_t si_utime; /* user time */ clock_t si_stime; /* system time */ }; /* core dumping signals */ - struct - { - void *si_addr; /* faulting address */ - }; + void *si_addr; /* faulting address */ }; } siginfo_t; #pragma pack(pop) @@ -77,7 +73,7 @@ enum unimplemented) */ SI_KERNEL, /* sent by system */ - ILL_ILLOP, /* illegal opcode */ + ILL_ILLOPC, /* illegal opcode */ ILL_ILLOPN, /* illegal operand */ ILL_ILLADR, /* illegal addressing mode */ ILL_ILLTRP, /* illegal trap*/ @@ -113,7 +109,7 @@ enum typedef struct sigevent { sigval_t sigev_value; /* signal value */ - int sigev_signo; /* signal number */ + int sigev_signo; /* signal number */ int sigev_notify; /* notification type */ void (*sigev_notify_function) (sigval_t); /* notification function */ pthread_attr_t *sigev_notify_attributes; /* notification attributes */ @@ -133,7 +129,7 @@ enum typedef void (*_sig_func_ptr)(int); -struct sigaction +struct sigaction { union { diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index 311e730..492ca3b 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -182,13 +182,13 @@ handle_sigprocmask (int sig, const sigset_t *set, sigset_t *oldset, sigset_t& op } static int -kill_worker (pid_t pid, int sig) +kill_worker (pid_t pid, siginfo_t& si) { sig_dispatch_pending (); int res = 0; pinfo dest (pid); - BOOL sendSIGCONT; + bool sendSIGCONT; if (!dest) { @@ -196,25 +196,32 @@ kill_worker (pid_t pid, int sig) return -1; } - if ((sendSIGCONT = (sig < 0))) - sig = -sig; + if ((sendSIGCONT = (si.si_signo < 0))) + si.si_signo = -si.si_signo; DWORD process_state = dest->process_state; - if (sig == 0) + if (si.si_signo == 0) { res = proc_exists (dest) ? 0 : -1; if (res < 0) set_errno (ESRCH); } - else if ((res = sig_send (dest, sig))) + else if ((res = sig_send (dest, si))) { sigproc_printf ("%d = sig_send, %E ", res); res = -1; } else if (sendSIGCONT) - (void) sig_send (dest, SIGCONT); + { + siginfo_t si2; + si2.si_signo = SIGCONT; + si2.si_code = SI_KERNEL; + si2.si_pid = si2.si_uid = si2.si_errno = 0; + (void) sig_send (dest, si2); + } - syscall_printf ("%d = kill_worker (%d, %d), process_state %p", res, pid, sig, process_state); + syscall_printf ("%d = kill_worker (%d, %d), process_state %p", res, pid, + si.si_signo, process_state); return res; } @@ -224,35 +231,54 @@ raise (int sig) return kill (myself->pid, sig); } -int -kill (pid_t pid, int sig) +static int +kill0 (pid_t pid, siginfo_t& si) { - syscall_printf ("kill (%d, %d)", pid, sig); + syscall_printf ("kill (%d, %d)", pid, si.si_signo); /* check that sig is in right range */ - if (sig < 0 || sig >= NSIG) + if (si.si_signo < 0 || si.si_signo >= NSIG) { set_errno (EINVAL); - syscall_printf ("signal %d out of range", sig); + syscall_printf ("signal %d out of range", si.si_signo); return -1; } /* Silently ignore stop signals from a member of orphaned process group. FIXME: Why??? */ if (ISSTATE (myself, PID_ORPHANED) && - (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)) - sig = 0; + (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)) + si.si_signo = 0; + + return (pid > 0) ? kill_worker (pid, si) : kill_pgrp (-pid, si); +} - return (pid > 0) ? kill_worker (pid, sig) : kill_pgrp (-pid, sig); +int +killsys (pid_t pid, int sig) +{ + siginfo_t si; + si.si_signo = sig; + si.si_code = SI_KERNEL; + si.si_pid = si.si_uid = si.si_errno = 0; + return kill0 (pid, si); +} +int +kill (pid_t pid, int sig) +{ + siginfo_t si; + si.si_signo = sig; + si.si_code = SI_USER; + si.si_pid = si.si_uid = si.si_errno = 0; + return kill0 (pid, si); } int -kill_pgrp (pid_t pid, int sig) +kill_pgrp (pid_t pid, siginfo_t& si) { int res = 0; int found = 0; int killself = 0; - sigproc_printf ("pid %d, signal %d", pid, sig); + sigproc_printf ("pid %d, signal %d", pid, si.si_signo); winpids pids ((DWORD) PID_MAP_RW); for (unsigned i = 0; i < pids.npids; i++) @@ -265,18 +291,18 @@ kill_pgrp (pid_t pid, int sig) /* Is it a process we want to kill? */ if ((pid == 0 && (p->pgid != myself->pgid || p->ctty != myself->ctty)) || (pid > 1 && p->pgid != pid) || - (sig < 0 && NOTSTATE (p, PID_STOPPED))) + (si.si_signo < 0 && NOTSTATE (p, PID_STOPPED))) continue; sigproc_printf ("killing pid %d, pgrp %d, p->ctty %d, myself->ctty %d", p->pid, p->pgid, p->ctty, myself->ctty); if (p == myself) killself++; - else if (kill_worker (p->pid, sig)) + else if (kill_worker (p->pid, si)) res = -1; found++; } - if (killself && kill_worker (myself->pid, sig)) + if (killself && kill_worker (myself->pid, si)) res = -1; if (!found) @@ -284,7 +310,7 @@ kill_pgrp (pid_t pid, int sig) set_errno (ESRCH); res = -1; } - syscall_printf ("%d = kill (%d, %d)", res, pid, sig); + syscall_printf ("%d = kill (%d, %d)", res, pid, si.si_signo); return res; } diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index e143a82..70129f6 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -48,41 +48,22 @@ details. */ #define NZOMBIES 256 -struct sigelem -{ - int sig; - int pid; - _threadinfo *tls; - class sigelem *next; - friend class pending_signals; - friend int __stdcall sig_dispatch_pending (); -}; - class pending_signals { - sigelem sigs[NSIG + 1]; - sigelem start; - sigelem *end; - sigelem *prev; - sigelem *curr; + sigpacket sigs[NSIG + 1]; + sigpacket start; + sigpacket *end; + sigpacket *prev; + sigpacket *curr; int empty; public: void reset () {curr = &start; prev = &start;} - void add (int sig, int pid, _threadinfo *tls); + void add (sigpacket&); void del (); - sigelem *next (); + sigpacket *next (); friend int __stdcall sig_dispatch_pending (); }; -struct sigpacket -{ - int sig; - pid_t pid; - HANDLE wakeup; - sigset_t *mask; - _threadinfo *tls; -}; - static pending_signals sigqueue; struct sigaction *global_sigs; @@ -563,9 +544,9 @@ sig_clear (int target_sig) else { sigqueue.reset (); - sigelem *q; + sigpacket *q; while ((q = sigqueue.next ())) - if (q->sig == target_sig) + if (q->si.si_signo == target_sig) { sigqueue.del (); break; @@ -670,13 +651,22 @@ sigproc_terminate (void) return; } +int __stdcall +sig_send (_pinfo *p, int sig) +{ + siginfo_t si; + si.si_signo = sig; + si.si_code = SI_KERNEL; + si.si_pid = si.si_uid = si.si_errno = 0; + return sig_send (p, si); +} + /* Send a signal to another process by raising its signal semaphore. - * If pinfo *p == NULL, send to the current process. - * If sending to this process, wait for notification that a signal has - * completed before returning. - */ + If pinfo *p == NULL, send to the current process. + If sending to this process, wait for notification that a signal has + completed before returning. */ int __stdcall -sig_send (_pinfo *p, int sig, void *tls) +sig_send (_pinfo *p, siginfo_t& si, _threadinfo *tls) { int rc = 1; bool its_me; @@ -703,11 +693,11 @@ sig_send (_pinfo *p, int sig, void *tls) if (!proc_can_be_signalled (p)) /* Is the process accepting messages? */ { sigproc_printf ("invalid pid %d(%x), signal %d", - p->pid, p->process_state, sig); + p->pid, p->process_state, si.si_signo); goto out; } - sigproc_printf ("pid %d, signal %d, its_me %d", p->pid, sig, its_me); + sigproc_printf ("pid %d, signal %d, its_me %d", p->pid, si.si_signo, its_me); if (its_me) { @@ -740,14 +730,18 @@ sig_send (_pinfo *p, int sig, void *tls) sigset_t pending; if (!its_me) pack.mask = NULL; - else if (sig == __SIGPENDING) + else if (si.si_signo == __SIGPENDING) pack.mask = &pending; - else if (sig == __SIGFLUSH || sig > 0) + else if (si.si_signo == __SIGFLUSH || si.si_signo > 0) pack.mask = &myself->getsigmask (); else pack.mask = NULL; - pack.sig = sig; + pack.si = si; + if (!pack.si.si_pid) + pack.si.si_pid = myself->pid; + if (!pack.si.si_uid) + pack.si.si_uid = myself->uid; pack.pid = myself->pid; pack.tls = (_threadinfo *) tls; DWORD nb; @@ -767,7 +761,7 @@ sig_send (_pinfo *p, int sig, void *tls) sigproc_printf ("I'm going away now"); else system_printf ("error sending signal %d to pid %d, pipe handle %p, %E", - sig, p->pid, sendsig); + si.si_signo, p->pid, sendsig); } goto out; } @@ -787,7 +781,8 @@ sig_send (_pinfo *p, int sig, void *tls) else { rc = WAIT_OBJECT_0; - sigproc_printf ("Not waiting for sigcomplete. its_me %d signal %d", its_me, sig); + sigproc_printf ("Not waiting for sigcomplete. its_me %d signal %d", + its_me, si.si_signo); if (!its_me) ForceCloseHandle (sendsig); } @@ -798,7 +793,7 @@ sig_send (_pinfo *p, int sig, void *tls) { if (!no_signals_available ()) system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E", - sig, rc); + si.si_signo, rc); set_errno (ENOSYS); rc = -1; } @@ -807,13 +802,13 @@ sig_send (_pinfo *p, int sig, void *tls) call_signal_handler_now (); out: - if (sig != __SIGPENDING) + if (si.si_signo != __SIGPENDING) /* nothing */; else if (!rc) rc = (int) pending; else rc = SIG_BAD_MASK; - sigproc_printf ("returning %p from sending signal %d", rc, sig); + sigproc_printf ("returning %p from sending signal %d", rc, si.si_signo); return rc; } @@ -1009,20 +1004,20 @@ talktome () has been handled, as per POSIX. */ void -pending_signals::add (int sig, int pid, _threadinfo *tls) +pending_signals::add (sigpacket& pack) { - sigelem *se; + sigpacket *se; for (se = start.next; se; se = se->next) - if (se->sig == sig) + if (se->si.si_signo == pack.si.si_signo) return; - while (sigs[empty].sig) + while (sigs[empty].si.si_signo) if (++empty == NSIG) empty = 0; se = sigs + empty; - se->sig = sig; + *se = pack; + se->mask_storage = *(pack.mask); + se->mask = &se->mask_storage; se->next = NULL; - se->tls = tls; - se->pid = pid; if (end) end->next = se; end = se; @@ -1034,9 +1029,9 @@ pending_signals::add (int sig, int pid, _threadinfo *tls) void pending_signals::del () { - sigelem *next = curr->next; + sigpacket *next = curr->next; prev->next = next; - curr->sig = 0; + curr->si.si_signo = 0; #ifdef DEBUGGING curr->next = NULL; #endif @@ -1046,10 +1041,10 @@ pending_signals::del () curr = next; } -sigelem * +sigpacket * pending_signals::next () { - sigelem *res; + sigpacket *res; prev = curr; if (!curr || !(curr = curr->next)) res = NULL; @@ -1125,7 +1120,7 @@ wait_sig (VOID *self) continue; } - if (!pack.sig) + if (!pack.si.si_signo) { #ifdef DEBUGGING system_printf ("zero signal?"); @@ -1140,8 +1135,8 @@ wait_sig (VOID *self) pack.mask = &dummy_mask; } - sigelem *q; - switch (pack.sig) + sigpacket *q; + switch (pack.si.si_signo) { case __SIGCOMMUNE: talktome (); @@ -1154,30 +1149,30 @@ wait_sig (VOID *self) unsigned bit; sigqueue.reset (); while ((q = sigqueue.next ())) - if (myself->getsigmask () & (bit = SIGTOMASK (q->sig))) + if (myself->getsigmask () & (bit = SIGTOMASK (q->si.si_signo))) *pack.mask |= bit; break; case __SIGFLUSH: sigqueue.reset (); while ((q = sigqueue.next ())) - if (sig_handle (q->sig, *pack.mask, q->pid, q->tls) > 0) + if (q->process () > 0) sigqueue.del (); break; default: - if (pack.sig < 0) - sig_clear (-pack.sig); + if (pack.si.si_signo < 0) + sig_clear (-pack.si.si_signo); else { - int sigres = sig_handle (pack.sig, *pack.mask, pack.pid, pack.tls); + int sigres = pack.process (); if (sigres <= 0) { #ifdef DEBUGGING2 if (!sigres) system_printf ("Failed to arm signal %d from pid %d", pack.sig, pack.pid); #endif - sigqueue.add (pack.sig, pack.pid, pack.tls);// FIXME: Shouldn't add this in !sh condition + sigqueue.add (pack); // FIXME: Shouldn't add this in !sh condition } - if (pack.sig == SIGCHLD) + if (pack.si.si_signo == SIGCHLD) proc_subproc (PROC_CLEARWAIT, 0); } break; @@ -1245,6 +1240,13 @@ wait_subproc (VOID *) rc -= WAIT_OBJECT_0; if (rc-- != 0) { + siginfo_t si; + si.si_signo = SIGCHLD; + si.si_code = SI_KERNEL; + si.si_pid = pchildren[rc]->pid; + si.si_uid = pchildren[rc]->uid; + si.si_errno = 0; + si.si_status = si.si_utime = si.si_stime = 0; // FIXME fill these in someday rc = proc_subproc (PROC_CHILDTERMINATED, rc); if (!proc_loop_wait) // Don't bother if wait_subproc is break; // exiting @@ -1253,7 +1255,7 @@ wait_subproc (VOID *) to avoid the proc_subproc lock since the signal thread will eventually be calling proc_subproc and could unnecessarily block. */ if (rc) - sig_send (myself_nowait, SIGCHLD); + sig_send (myself_nowait, si); } sigproc_printf ("looping"); } diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index f34dfa2..03ee1b8 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -48,6 +48,21 @@ typedef struct struct_waitq HANDLE thread_ev; } waitq; +struct sigpacket +{ + siginfo_t si; + pid_t pid; + class _threadinfo *tls; + sigset_t *mask; + sigset_t mask_storage; + union + { + HANDLE wakeup; + struct sigpacket *next; + }; + int __stdcall process () __attribute__ ((regparm (1))); +}; + extern HANDLE signal_arrived; extern HANDLE sigCONT; @@ -62,9 +77,6 @@ int __stdcall handle_sigprocmask (int sig, const sigset_t *set, extern "C" void __stdcall reset_signal_arrived (); extern "C" int __stdcall call_signal_handler_now (); -#ifdef _CYGTLS_H -int __stdcall sig_handle (int, sigset_t, int, _threadinfo *) __attribute__ ((regparm (3))); -#endif void __stdcall sig_clear (int) __attribute__ ((regparm (1))); void __stdcall sig_set_pending (int) __attribute__ ((regparm (1))); int __stdcall handle_sigsuspend (sigset_t); @@ -78,12 +90,16 @@ void __stdcall subproc_init (); void __stdcall sigproc_terminate (); bool __stdcall proc_exists (_pinfo *) __attribute__ ((regparm(1))); bool __stdcall pid_exists (pid_t) __attribute__ ((regparm(1))); -int __stdcall sig_send (_pinfo *, int, void * = NULL) __attribute__ ((regparm(3))); +int __stdcall sig_send (_pinfo *, siginfo_t&, class _threadinfo *tls = NULL) __attribute__ ((regparm (3))); +int __stdcall sig_send (_pinfo *, int) __attribute__ ((regparm (2))); void __stdcall signal_fixup_after_fork (); void __stdcall signal_fixup_after_exec (); void __stdcall wait_for_sigthread (); void __stdcall sigalloc (); +int kill_pgrp (pid_t, siginfo_t&); +int killsys (pid_t, int); + extern char myself_nowait_dummy[]; extern struct sigaction *global_sigs; diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc index ae03dc6..0b17825 100644 --- a/winsup/cygwin/thread.cc +++ b/winsup/cygwin/thread.cc @@ -2736,7 +2736,11 @@ pthread_kill (pthread_t thread, int sig) if (!pthread::is_good_object (&thread)) return EINVAL; - int rval = sig ? sig_send (NULL, sig, thread->cygtls) : 0; + siginfo_t si; + si.si_signo = sig; + si.si_code = SI_USER; + si.si_pid = si.si_uid = si.si_errno = 0; + int rval = sig ? sig_send (NULL, si, thread->cygtls) : 0; // unlock myself return rval; diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h index 6c2e58f..f8bb9ec 100644 --- a/winsup/cygwin/winsup.h +++ b/winsup/cygwin/winsup.h @@ -318,10 +318,6 @@ int cygwin_select (int , fd_set *, fd_set *, fd_set *, struct timeval *to); int cygwin_gethostname (char *__name, size_t __len); -int kill_pgrp (pid_t, int); -int _kill (int, int); -int _raise (int sig); - extern DWORD binmode; extern char _data_start__, _data_end__, _bss_start__, _bss_end__; extern void (*__CTOR_LIST__) (void); -- cgit v1.1