From f6936c48f382a12b7b67fda40352b8e377662743 Mon Sep 17 00:00:00 2001 From: Christopher Faylor Date: Mon, 19 Jan 2004 05:46:54 +0000 Subject: * cygwin/include/signal.h: Add copyright notice. * cygwin.din: Make clock SIGFE. Add clock_gettime, sigwaitinfo, timer_create, timer_delete, timer_settime. * include/cygwin/version.h: Reflect above additions. * fork.cc (fork_child): Call fixup_timers_after_fork. * signal.cc (sigwait): Remove unused variable. * timer.cc: New file. (clock_gettime): Define new function. (timer_tracker): Define new struct used by timer functions. (timer_tracker::timer_tracker): New function. (to_us): New function. (timer_thread): New function. (timer_tracker::settime): New function. (timer_create): New function. (timer_settime): New function. (timer_delete): New function. (fixup_timers_after_fork): New function. * cygthread.cc: Bump thread count. * signal.cc (sigwaitinfo): Define new function. (sigwait): Redefine based on sigwaitinfo. * include/cygwin/signal.h (sigwaitinfo): Declare. (sigwait): Ditto. * dtable.cc (dtable::vfork_parent_restore): Avoid double close of ctty when ctty == ctty_on_hold. * cygtls.h (_threadinfo::threadkill): New element. (_threadinfo::set_threadkill): Declare new function. (_threadinfo::reset_threadkill): Declare new function. * dcrt0.cc (dcrt0_1): Call here so that it will be possible to attach to running process with #(*& Windows Me/9x. (initial_env): Try to initialize strace if uninitialized. * gendef: Don't zero signal if threadkill is set since that will happen in the called function. * signal.cc (sigwait): Ensure cleanup in error conditions. * sigproc.cc (sig_send): Clear packet mask storage. (wait_subproc): Fill in child exit code in siginfo_t structure. * thread.cc (pthread_kill): Set threadkill flag. * tlsoffsets.h: Regenerate. Throughout, use siginfo_t to fill out all signal information for "kernel" signals. * cygtls.h (_threadinfo::set_siginfo): Declare new function. * cygtls.cc (_threadinfo::set_siginfo): Define new function. * dcrt0.cc (do_exit): Accommodate siginfo_t considerations. * exceptions.cc (handle_exceptions): Ditto. (sig_handle_tty_stop): Ditto. (ctrl_c_handler): Use killsys() to send signal. (sigpacket::process): Rename from sig_handle. Use siginfo_t field from sigpacket for everything. (tty_min::kill_pgrp): Accommodate siginfo_t considerations. (fhandler_termios::bg_check): Ditto. * fhandler_tty.cc (fhandler_tty_slave::ioctl): Use killsys() to send signal. * signal.cc (kill_worker): Rewrite to use siginfo_t second argument. (kill_pgrp): Ditto. (kill0): Define new function pulled from kill(). (kill): Rewrite as frontend to kill0. (killsys): Define new function. * sigproc.cc (sigelem): Eliminate. (sigpacket): Move to sigproc.h. Subsume sigelem. (pending_signals): Use sigpacket rather than sigelem for everything. (sig_clear): Ditto. (wait_sig): Ditto. (sig_send): Rewrite to use siginfo_t argument. (sig_send): New function wratpper to sig_send with siginfo_t argument. (wait_subproc): Accommodate siginfo_t considerations. * thread.cc (pthread_kill): Ditto. * sigproc.h (sigpacket): Move here. (sigpacket::process): Declare "new" function. (sig_handle): Eliminate declaration. (sig_send): Declare with new paramaters. (killsys): Declare new function. (kill_pgrp): Declare. * winsup.h: Move some signal-specific stuff to sigproc.h. * include/cygwin/signal.h: Tweak some siginfo_t stuff. --- winsup/cygwin/sigproc.cc | 140 +++++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 65 deletions(-) (limited to 'winsup/cygwin/sigproc.cc') diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index e143a8239..a1c2d305d 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,16 +730,21 @@ 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; + pack.mask_storage = 0; DWORD nb; if (!WriteFile (sendsig, &pack, sizeof (pack), &nb, NULL) || nb != sizeof (pack)) { @@ -767,7 +762,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 +782,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 +794,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 +803,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 +1005,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 +1030,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 +1042,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 +1121,7 @@ wait_sig (VOID *self) continue; } - if (!pack.sig) + if (!pack.si.si_signo) { #ifdef DEBUGGING system_printf ("zero signal?"); @@ -1140,8 +1136,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 +1150,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 +1241,20 @@ 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; + GetExitCodeProcess (hchildren[rc], (DWORD *) &si.si_status); +#if 0 // FIXME: This is tricky to get right + si.si_utime = pchildren[rc]->rusage_self.ru_utime; + si.si_stime = pchildren[rc].rusage_self.ru_stime; +#else + si.si_utime = 0; + si.si_stime = 0; +#endif rc = proc_subproc (PROC_CHILDTERMINATED, rc); if (!proc_loop_wait) // Don't bother if wait_subproc is break; // exiting @@ -1253,7 +1263,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"); } -- cgit v1.2.3