* 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

@ -1,3 +1,91 @@
2004-01-19 Christopher Faylor <cgf@redhat.com>
* 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.
2004-01-17 Christopher Faylor <cgf@redhat.com>
* signal.cc (sigwaitinfo): Define new function.
(sigwait): Redefine based on sigwaitinfo.
* include/cygwin/signal.h (sigwaitinfo): Declare.
(sigwait): Ditto.
2004-01-17 Christopher Faylor <cgf@redhat.com>
* dtable.cc (dtable::vfork_parent_restore): Avoid double close of ctty
when ctty == ctty_on_hold.
2004-01-16 Christopher Faylor <cgf@redhat.com>
* 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.
2004-01-16 Christopher Faylor <cgf@redhat.com>
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.
2004-01-16 Christopher Faylor <cgf@redhat.com>
* fhandler_console.cc (fhandler_console::close): Remove obsolete test

View File

@ -134,7 +134,7 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o cxx.o cygheap.o cygthread.o cygtls.o \
resource.o scandir.o sched.o sec_acl.o sec_helper.o security.o \
select.o sem.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \
spawn.o strace.o strsep.o sync.o syscalls.o sysconf.o syslog.o \
termios.o thread.o times.o tty.o uinfo.o uname.o v8_regexp.o \
termios.o thread.o timer.o times.o tty.o uinfo.o uname.o v8_regexp.o \
v8_regerror.o v8_regsub.o wait.o wincap.o window.o \
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)

View File

@ -20,7 +20,7 @@ details. */
#undef CloseHandle
static cygthread NO_COPY threads[18];
static cygthread NO_COPY threads[32];
#define NTHREADS (sizeof (threads) / sizeof (threads[0]))
DWORD NO_COPY cygthread::main_thread_id;

View File

@ -1,6 +1,6 @@
/* cygthread.h
Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for

View File

@ -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 *)

View File

@ -102,6 +102,7 @@ struct _threadinfo
sigset_t sigmask;
sigset_t sigwait_mask;
siginfo_t *sigwait_info;
unsigned threadkill;
siginfo_t infodata;
struct pthread *tid;
struct _reent local_clib;
@ -120,7 +121,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 +132,9 @@ 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)));
void set_threadkill () {threadkill = true;}
void reset_threadkill () {threadkill = false;}
/*gentls_offsets*/
};
#pragma pack(pop)

View File

@ -246,8 +246,9 @@ _chroot = chroot SIGFE
cleanup_glue NOSIGFE
clearerr NOSIGFE
_clearerr = clearerr NOSIGFE
clock NOSIGFE
_clock = clock NOSIGFE
clock SIGFE
_clock = clock SIGFE
clock_gettime SIGFE
close SIGFE
_close = close SIGFE
closedir SIGFE
@ -1234,6 +1235,7 @@ sigpending SIGFE
sigprocmask SIGFE
sigsuspend SIGFE
sigwait SIGFE
sigwaitinfo SIGFE
sin NOSIGFE
_sin = sin NOSIGFE
sincos NOSIGFE
@ -1407,6 +1409,9 @@ tgamma NOSIGFE
tgammaf NOSIGFE
time SIGFE
_time = time SIGFE
timer_create SIGFE
timer_delete SIGFE
timer_settime SIGFE
times SIGFE
_times = times SIGFE
timezone SIGFE

View File

@ -542,8 +542,12 @@ initial_env ()
buf[0] = '\0';
len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
while (ms--)
Sleep (1);
Sleep (ms);
if (!strace.active)
{
strace.inited = 0;
strace.hello ();
}
}
if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
{
@ -573,7 +577,6 @@ void __stdcall
dll_crt0_0 ()
{
wincap.init ();
initial_env ();
char zeros[sizeof (child_proc_info->zero)] = {0};
@ -719,6 +722,7 @@ dll_crt0_1 (char *)
/* FIXME: Verify forked children get their exception handler set up ok. */
exception_list cygwin_except_entry;
initial_env ();
check_sanity_and_sync (user_data);
malloc_init ();
@ -1042,9 +1046,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);
}
}

View File

@ -1,6 +1,6 @@
/* dtable.h: fd table definition.
Copyright 2000, 2001, 2003 Red Hat, Inc.
Copyright 2000, 2001, 2003, 2004 Red Hat, Inc.
This file is part of Cygwin.

View File

@ -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,14 @@ 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
}
si.si_addr = ebp;
si.si_code = SI_KERNEL;
si.si_errno = si.si_pid = si.si_uid = 0;
_my_tls.push ((__stack_t) ebp, true);
sig_send (NULL, sig, &_my_tls); // Signal myself
sig_send (NULL, si, &_my_tls); // Signal myself
return 1;
}
#endif /* __i386__ */
@ -605,7 +632,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 +848,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 +883,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 +918,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 +935,56 @@ 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 special_case = ISSTATE (myself, PID_STOPPED) || main_vfork->pid;
bool masked = sigismember (&mask, sig);
if (sig != SIGKILL && sig != SIGSTOP
&& (special_case || main_vfork->pid || masked || insigwait_mask
|| (tls && sigismember (&tls->sigmask, sig))))
sigproc_printf ("signal %d processing", si.si_signo);
struct sigaction thissig = global_sigs[si.si_signo];
myself->rusage_self.ru_nsignals++;
if (si.si_signo == SIGKILL)
goto exit_sig;
if ( si.si_signo == SIGSTOP)
{
sigproc_printf ("signal %d blocked", sig);
if ((!special_case && !masked)
&& (insigwait_mask || (tls = _threadinfo::find_tls (sig)) != NULL))
goto thread_specific;
sig_clear (SIGCONT);
goto stop;
}
bool masked;
bool special_case;
bool insigwait_mask;
insigwait_mask = masked = false;
if (special_case = (main_vfork->pid || ISSTATE (myself, PID_STOPPED)))
/* nothing to do */;
else if (tls && sigismember (&tls->sigwait_mask, si.si_signo))
insigwait_mask = true;
else if (!tls && (tls = _threadinfo::find_tls (si.si_signo)))
insigwait_mask = true;
else if (!(masked = sigismember (mask, si.si_signo)) && tls)
masked = sigismember (&tls->sigmask, si.si_signo);
if (insigwait_mask)
goto thread_specific;
if (!tls)
tls = _main_tls;
if (special_case || masked)
{
sigproc_printf ("signal %d blocked", si.si_signo);
rc = -1;
goto done;
}
/* Clear pending SIGCONT on stop signals */
if (sig == SIGSTOP || sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)
sig_clear (SIGCONT);
sigproc_printf ("signal %d processing", sig);
struct sigaction thissig = global_sigs[sig];
void *handler;
handler = (void *) thissig.sa_handler;
myself->rusage_self.ru_nsignals++;
if (sig == SIGKILL)
goto exit_sig;
if (sig == SIGSTOP)
goto stop;
/* Clear pending SIGCONT on stop signals */
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
sig_clear (SIGCONT);
#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 +992,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 +1007,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 +1022,38 @@ 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;
tls->set_siginfo (this);
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 */
}

View File

@ -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:

View File

@ -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:

View File

@ -231,6 +231,7 @@ sync_with_parent (const char *s, bool hang_self)
static int __stdcall
fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
{
extern void fixup_timers_after_fork ();
debug_printf ("child is running. pid %d, ppid %d, stack here %p",
myself->pid, myself->ppid, __builtin_frame_address (0));
@ -316,6 +317,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
(*t)->set ();
pthread::atforkchild ();
fixup_timers_after_fork ();
wait_for_sigthread ();
cygbench ("fork-child");
return 0;

View File

@ -169,10 +169,12 @@ _sigdelayed:
pushl $tls::newmask(%ebx) # newmask - eaten by set_process_mask
call _set_process_mask\@4
cmpl \$0,$tls::threadkill(%ebx)#pthread_kill signal?
jnz 4f #yes. Callee clears signal number
movl \$0,$tls::sig(%ebx) # zero the signal number as a
# flag to the signal handler thread
# that it is ok to set up sigsave
popl %ebx
4: popl %ebx
jmp *%ebx
EOF

View File

@ -1,6 +1,20 @@
/* signal.h
Copyright 2004 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#ifndef _CYGWIN_SIGNAL_H
#define _CYGWIN_SIGNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#if 0
struct ucontext
{
@ -8,7 +22,7 @@ struct ucontext
void *uc_link;
stack_t uc_stack;
struct sigcontext uc_mcontext;
sigset_t uc_sigmask;
sigset_t uc_sigmask;
};
#endif
@ -18,49 +32,55 @@ typedef union sigval
void *sival_ptr; /* pointer signal value */
} sigval_t;
typedef struct sigevent
{
sigval_t sigev_value; /* signal value */
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 */
} sigevent_t;
#pragma pack(push,4)
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[32]; /* plan for future growth */
union
{
/* timers */
/* timers */
struct
{
unsigned int si_tid; /* timer id */
unsigned int si_overrun; /* overrun count */
union
{
struct
{
timer_t si_tid; /* timer id */
unsigned int si_overrun; /* overrun count */
};
sigval_t si_sigval; /* signal value */
sigval_t si_value; /* 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 +97,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*/
@ -110,15 +130,6 @@ enum
CLD_CONTINUED /* stopped child has continued */
};
typedef struct sigevent
{
sigval_t sigev_value; /* signal value */
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 */
} sigevent_t;
enum
{
SIGEV_SIGNAL = 0, /* a queued signal, with an application
@ -133,7 +144,7 @@ enum
typedef void (*_sig_func_ptr)(int);
struct sigaction
struct sigaction
{
union
{
@ -188,4 +199,10 @@ struct sigaction
#define SIGUSR1 30 /* user defined signal 1 */
#define SIGUSR2 31 /* user defined signal 2 */
#define NSIG 32 /* signal 0 implied */
int sigwait (const sigset_t *, int *);
int sigwaitinfo (const sigset_t *, siginfo_t *);
#ifdef __cplusplus
}
#endif
#endif /*_CYGWIN_SIGNAL_H*/

View File

@ -233,12 +233,14 @@ details. */
106: Export flock.
107: Export fcntl64.
108: Remove unused (hopefully) reent_data export.
109: Export clock_gettime, sigwaitinfo, timer_create, timer_delete,
timer_settime
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
#define CYGWIN_VERSION_API_MINOR 108
#define CYGWIN_VERSION_API_MINOR 109
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible

View File

@ -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, sig) : kill_pgrp (-pid, sig);
return (pid > 0) ? kill_worker (pid, si) : kill_pgrp (-pid, si);
}
int
kill_pgrp (pid_t pid, int sig)
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, 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;
}
@ -452,12 +478,21 @@ siginterrupt (int sig, int flag)
return sigaction (sig, &act, NULL);
}
extern "C" int
sigwait (const sigset_t *set, int *sig_ptr)
{
int sig = sigwaitinfo (set, NULL);
if (sig > 0)
*sig_ptr = sig;
return sig > 0 ? 0 : -1;
}
extern "C" int
sigwait (const sigset_t *set, int *sig)
sigwaitinfo (const sigset_t *set, siginfo_t *info)
{
pthread_testcancel ();
_my_tls.event = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
HANDLE h;
h = _my_tls.event = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
if (!_my_tls.event)
{
__seterrno ();
@ -466,16 +501,22 @@ sigwait (const sigset_t *set, int *sig)
_my_tls.sigwait_mask = *set;
int res;
switch (WaitForSingleObject (_my_tls.event, INFINITE))
{
case WAIT_OBJECT_0:
CloseHandle (_my_tls.event);
_my_tls.event = NULL;
*sig = InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
res = _my_tls.infodata.si_signo;
sigproc_printf ("returning sig %d", res);
if (info)
*info = _my_tls.infodata;
break;
default:
__seterrno ();
return -1;
res = -1;
}
return 0;
_my_tls.event = NULL;
InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
CloseHandle (h);
sig_dispatch_pending ();
return res;
}

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

View File

@ -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;

View File

@ -85,7 +85,7 @@ static int __stdcall stat_worker (const char *name, struct __stat64 *buf,
ensure we don't leave any such files lying around. */
void __stdcall
close_all_files (void)
close_all_files ()
{
cygheap->fdtab.lock ();

View File

@ -2736,7 +2736,12 @@ 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;
thread->cygtls->set_threadkill ();
int rval = sig ? sig_send (NULL, si, thread->cygtls) : 0;
// unlock myself
return rval;

275
winsup/cygwin/timer.cc Normal file
View File

@ -0,0 +1,275 @@
/* timer.cc
Copyright 2004 Red Hat, Inc.
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
#include "winsup.h"
#include <time.h>
#include <stdlib.h>
#include "cygerrno.h"
#include "security.h"
#include "hires.h"
#include "thread.h"
#include "cygtls.h"
#include "cygthread.h"
#include "sigproc.h"
#include "sync.h"
#define TT_MAGIC 0x513e4a1c
struct timer_tracker
{
static muto *protect;
unsigned magic;
clockid_t clock_id;
sigevent evp;
itimerspec it;
HANDLE cancel;
int flags;
cygthread *th;
struct timer_tracker *next;
int settime (int, const itimerspec *, itimerspec *);
timer_tracker (clockid_t, const sigevent *);
timer_tracker ();
};
timer_tracker ttstart;
muto *timer_tracker::protect;
timer_tracker::timer_tracker ()
{
new_muto (protect);
}
timer_tracker::timer_tracker (clockid_t c, const sigevent *e)
{
if (e != NULL)
evp = *e;
else
{
evp.sigev_notify = SIGEV_SIGNAL;
evp.sigev_signo = SIGALRM;
evp.sigev_value.sival_ptr = this;
}
clock_id = c;
cancel = NULL;
flags = 0;
memset (&it, 0, sizeof (it));
protect->acquire ();
next = ttstart.next;
ttstart.next = this;
protect->release ();
magic = TT_MAGIC;
}
static long long
to_us (timespec& ts)
{
long long res = ts.tv_sec;
res *= 1000000;
res += ts.tv_nsec / 1000 + ((ts.tv_nsec % 1000) >= 500 ? 1 : 0);
return res;
}
static NO_COPY itimerspec itzero;
static NO_COPY timespec tzero;
static DWORD WINAPI
timer_thread (VOID *x)
{
timer_tracker *tp = ((timer_tracker *) x);
timer_tracker tt = *tp;
for (bool first = true; ; first = false)
{
long long sleep_us = to_us (first ? tt.it.it_value : tt.it.it_interval);
long long sleep_to = sleep_us;
long long now = gtod.usecs (false);
if (tt.flags & TIMER_ABSTIME)
sleep_us -= now;
else
sleep_to += now;
DWORD sleep_ms = (sleep_us < 0) ? 0 : (sleep_us / 1000);
debug_printf ("%p waiting for %u ms, first %d", x, sleep_ms, first);
tp->it.it_value = tzero;
switch (WaitForSingleObject (tt.cancel, sleep_ms))
{
case WAIT_TIMEOUT:
debug_printf ("timed out");
break;
case WAIT_OBJECT_0:
now = gtod.usecs (false);
sleep_us = sleep_to - now;
if (sleep_us < 0)
sleep_us = 0;
tp->it.it_value.tv_sec = sleep_us / 1000000;
tp->it.it_value.tv_nsec = (sleep_us % 1000000) * 1000;
debug_printf ("%p cancelled, elapsed %D", x, sleep_us);
goto out;
default:
debug_printf ("%p timer wait failed, %E", x);
goto out;
}
switch (tt.evp.sigev_notify)
{
case SIGEV_SIGNAL:
{
siginfo_t si;
memset (&si, 0, sizeof (si));
si.si_signo = tt.evp.sigev_signo;
si.si_sigval.sival_ptr = tt.evp.sigev_value.sival_ptr;
debug_printf ("%p sending sig %d", x, tt.evp.sigev_signo);
sig_send (NULL, si);
break;
}
case SIGEV_THREAD:
{
pthread_t notify_thread;
debug_printf ("%p starting thread", x);
int rc = pthread_create (&notify_thread, tt.evp.sigev_notify_attributes,
(void * (*) (void *)) tt.evp.sigev_notify_function,
&tt.evp.sigev_value);
if (rc)
{
debug_printf ("thread creation failed, %E");
return 0;
}
// FIXME: pthread_join?
break;
}
}
if (!tt.it.it_interval.tv_sec && !tt.it.it_interval.tv_nsec)
break;
tt.flags = 0;
debug_printf ("looping");
}
out:
CloseHandle (tt.cancel);
// FIXME: race here but is it inevitable?
if (tt.cancel == tp->cancel)
tp->cancel = NULL;
return 0;
}
static bool
it_bad (const timespec& t)
{
if (t.tv_nsec < 0 || t.tv_nsec >= 1000000000 || t.tv_sec < 0)
{
set_errno (EINVAL);
return true;
}
return false;
}
int
timer_tracker::settime (int in_flags, const itimerspec *value, itimerspec *ovalue)
{
if (!value)
{
set_errno (EINVAL);
return -1;
}
if (__check_invalid_read_ptr_errno (value, sizeof (*value)))
return -1;
if (ovalue && check_null_invalid_struct_errno (ovalue))
return -1;
itimerspec *elapsed;
if (!cancel)
elapsed = &itzero;
else
{
SetEvent (cancel); // should be closed when the thread exits
th->detach ();
elapsed = &it;
}
if (ovalue)
*ovalue = *elapsed;
if (value->it_value.tv_sec || value->it_value.tv_nsec)
{
if (it_bad (value->it_value))
return -1;
if (it_bad (value->it_interval))
return -1;
flags = in_flags;
cancel = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
it = *value;
th = new cygthread (timer_thread, this, "itimer");
}
return 0;
}
extern "C" int
timer_create (clockid_t clock_id, struct sigevent *evp, timer_t *timerid)
{
if (evp && check_null_invalid_struct_errno (evp))
return -1;
if (check_null_invalid_struct_errno (timerid))
return -1;
if (clock_id != CLOCK_REALTIME)
{
set_errno (EINVAL);
return -1;
}
*timerid = (timer_t) new timer_tracker (clock_id, evp);
return 0;
}
extern "C" int
timer_settime (timer_t timerid, int flags, const struct itimerspec *value,
struct itimerspec *ovalue)
{
timer_tracker *tt = (timer_tracker *) timerid;
if (check_null_invalid_struct_errno (tt) || tt->magic != TT_MAGIC)
return -1;
return tt->settime (flags, value, ovalue);
}
extern "C" int
timer_delete (timer_t timerid)
{
timer_tracker *in_tt = (timer_tracker *) timerid;
if (check_null_invalid_struct_errno (in_tt) || in_tt->magic != TT_MAGIC)
return -1;
timer_tracker::protect->acquire ();
for (timer_tracker *tt = &ttstart; tt->next != NULL; tt = tt->next)
if (tt->next == in_tt)
{
timer_tracker *deleteme = tt->next;
tt->next = deleteme->next;
delete deleteme;
timer_tracker::protect->release ();
return 0;
}
timer_tracker::protect->release ();
set_errno (EINVAL);
return 0;
}
void
fixup_timers_after_fork ()
{
for (timer_tracker *tt = &ttstart; tt->next != NULL; /* nothing */)
{
timer_tracker *deleteme = tt->next;
tt->next = deleteme->next;
delete deleteme;
}
}

View File

@ -1,6 +1,6 @@
/* times.cc
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
This file is part of Cygwin.
@ -15,6 +15,7 @@ details. */
#include <utime.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "cygerrno.h"
#include "security.h"
#include "path.h"
@ -22,6 +23,9 @@ details. */
#include "pinfo.h"
#include "hires.h"
#include "cygtls.h"
#include "cygthread.h"
#include "sigproc.h"
#include "sync.h"
#define FACTOR (0x19db1ded53e8000LL)
#define NSPERSEC 10000000LL
@ -612,7 +616,8 @@ hires_us::usecs (bool justdelta)
// FIXME: Use round() here?
now.QuadPart = (LONGLONG) (freq * (double) (now.QuadPart - primed_pc.QuadPart));
return justdelta ? now.QuadPart : primed_ft.QuadPart + now.QuadPart;
LONGLONG res = justdelta ? now.QuadPart : primed_ft.QuadPart + now.QuadPart;
return res;
}
UINT
@ -657,3 +662,21 @@ hires_ms::usecs (bool justdelta)
LONGLONG res = initime_us.QuadPart + ((LONGLONG) (now - initime_ms) * 1000);
return res;
}
extern "C" int
clock_gettime (clockid_t clk_id, struct timespec *tp)
{
if (clk_id != CLOCK_REALTIME)
{
set_errno (ENOSYS);
return -1;
}
LONGLONG now = gtod.usecs (false);
if (now == (LONGLONG) -1)
return -1;
tp->tv_sec = now / 1000000;
tp->tv_nsec = (now % 1000000) * 1000;
return 0;
}

View File

@ -1,17 +1,18 @@
//;# autogenerated: Do not edit.
//; $tls::func = -4076;
//; $tls::saved_errno = -4072;
//; $tls::sa_flags = -4068;
//; $tls::oldmask = -4064;
//; $tls::newmask = -4060;
//; $tls::event = -4056;
//; $tls::errno_addr = -4052;
//; $tls::initialized = -4048;
//; $tls::sigmask = -4044;
//; $tls::sigwait_mask = -4040;
//; $tls::sigwait_info = -4036;
//; $tls::infodata = -4032;
//; $tls::func = -3704;
//; $tls::saved_errno = -3700;
//; $tls::sa_flags = -3696;
//; $tls::oldmask = -3692;
//; $tls::newmask = -3688;
//; $tls::event = -3684;
//; $tls::errno_addr = -3680;
//; $tls::initialized = -3676;
//; $tls::sigmask = -3672;
//; $tls::sigwait_mask = -3668;
//; $tls::sigwait_info = -3664;
//; $tls::threadkill = -3660;
//; $tls::infodata = -3656;
//; $tls::tid = -3508;
//; $tls::local_clib = -3504;
//; $tls::locals = -2576;
@ -23,18 +24,19 @@
//; $tls::padding = 0;
//; __DATA__
#define tls_func (-4076)
#define tls_saved_errno (-4072)
#define tls_sa_flags (-4068)
#define tls_oldmask (-4064)
#define tls_newmask (-4060)
#define tls_event (-4056)
#define tls_errno_addr (-4052)
#define tls_initialized (-4048)
#define tls_sigmask (-4044)
#define tls_sigwait_mask (-4040)
#define tls_sigwait_info (-4036)
#define tls_infodata (-4032)
#define tls_func (-3704)
#define tls_saved_errno (-3700)
#define tls_sa_flags (-3696)
#define tls_oldmask (-3692)
#define tls_newmask (-3688)
#define tls_event (-3684)
#define tls_errno_addr (-3680)
#define tls_initialized (-3676)
#define tls_sigmask (-3672)
#define tls_sigwait_mask (-3668)
#define tls_sigwait_info (-3664)
#define tls_threadkill (-3660)
#define tls_infodata (-3656)
#define tls_tid (-3508)
#define tls_local_clib (-3504)
#define tls_locals (-2576)

View File

@ -219,7 +219,7 @@ void uinfo_init (void);
void events_init (void);
void events_terminate (void);
void __stdcall close_all_files (void);
void __stdcall close_all_files ();
/* Invisible window initialization/termination. */
HWND __stdcall gethwnd (void);
@ -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);