* 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.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
int __stdcall
|
||||
sig_send (_pinfo *p, int sig, void *tls)
|
||||
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. */
|
||||
int __stdcall
|
||||
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");
|
||||
}
|
||||
|
Reference in New Issue
Block a user