* 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:
Christopher Faylor
2004-01-19 05:46:54 +00:00
parent 49fec4c011
commit f6936c48f3
25 changed files with 819 additions and 253 deletions

View File

@@ -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");
}