* 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> 2004-01-16 Christopher Faylor <cgf@redhat.com>
* fhandler_console.cc (fhandler_console::close): Remove obsolete test * 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 \ 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 \ 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 \ 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 \ v8_regerror.o v8_regsub.o wait.o wincap.o window.o \
$(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS) $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS)

View File

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

View File

@ -1,6 +1,6 @@
/* cygthread.h /* 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 This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for Cygwin license. Please consult the file "CYGWIN_LICENSE" for

View File

@ -20,6 +20,7 @@ details. */
#include "dtable.h" #include "dtable.h"
#include "cygheap.h" #include "cygheap.h"
#include "cygthread.h" #include "cygthread.h"
#include "sigproc.h"
class sentry class sentry
{ {
@ -189,6 +190,12 @@ _threadinfo::find_tls (int sig)
return res; return res;
} }
void
_threadinfo::set_siginfo (sigpacket *pack)
{
infodata = pack->si;
}
extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD); extern "C" DWORD __stdcall RtlUnwind (void *, void *, void *, DWORD);
static int static int
handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *, void *) handle_threadlist_exception (EXCEPTION_RECORD *e, void *frame, CONTEXT *, void *)

View File

@ -102,6 +102,7 @@ struct _threadinfo
sigset_t sigmask; sigset_t sigmask;
sigset_t sigwait_mask; sigset_t sigwait_mask;
siginfo_t *sigwait_info; siginfo_t *sigwait_info;
unsigned threadkill;
siginfo_t infodata; siginfo_t infodata;
struct pthread *tid; struct pthread *tid;
struct _reent local_clib; struct _reent local_clib;
@ -120,7 +121,7 @@ struct _threadinfo
static void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3))); static void call2 (DWORD (*) (void *, void *), void *, void *) __attribute__ ((regparm (3)));
static struct _threadinfo *find_tls (int sig); static struct _threadinfo *find_tls (int sig);
void remove (DWORD); void remove (DWORD);
void push (__stack_t, bool = false); void push (__stack_t, bool = false) __attribute__ ((regparm (3)));
__stack_t pop (); __stack_t pop ();
bool isinitialized () {return initialized == CYGTLS_INITIALIZED || initialized == CYGTLS_EXCEPTION;} bool isinitialized () {return initialized == CYGTLS_INITIALIZED || initialized == CYGTLS_EXCEPTION;}
void set_state (bool); void set_state (bool);
@ -131,6 +132,9 @@ struct _threadinfo
__attribute__((regparm(3))); __attribute__((regparm(3)));
void init_threadlist_exceptions (struct _exception_list *); void init_threadlist_exceptions (struct _exception_list *);
operator HANDLE () const {return tid->win32_obj_id;} 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*/ /*gentls_offsets*/
}; };
#pragma pack(pop) #pragma pack(pop)

View File

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

View File

@ -542,8 +542,12 @@ initial_env ()
buf[0] = '\0'; buf[0] = '\0';
len = GetModuleFileName (NULL, buf, CYG_MAX_PATH); len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf); console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
while (ms--) Sleep (ms);
Sleep (1); if (!strace.active)
{
strace.inited = 0;
strace.hello ();
}
} }
if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1)) if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
{ {
@ -573,7 +577,6 @@ void __stdcall
dll_crt0_0 () dll_crt0_0 ()
{ {
wincap.init (); wincap.init ();
initial_env ();
char zeros[sizeof (child_proc_info->zero)] = {0}; 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. */ /* FIXME: Verify forked children get their exception handler set up ok. */
exception_list cygwin_except_entry; exception_list cygwin_except_entry;
initial_env ();
check_sanity_and_sync (user_data); check_sanity_and_sync (user_data);
malloc_init (); malloc_init ();
@ -1042,9 +1046,13 @@ do_exit (int status)
/* Kill orphaned children on group leader exit */ /* Kill orphaned children on group leader exit */
if (myself->has_pgid_children && myself->pid == myself->pgid) 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", sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
myself->pid, myself->pgid); 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. /* 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. 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); RtlUnwind (frame, ret_here, e0, 0);
__asm__ volatile (".equ _ret_here,."); __asm__ volatile (".equ _ret_here,.");
int sig; siginfo_t si;
/* Coerce win32 value to posix value. */ /* Coerce win32 value to posix value. */
switch (e.ExceptionCode) switch (e.ExceptionCode)
{ {
case STATUS_FLOAT_DENORMAL_OPERAND: case STATUS_FLOAT_DENORMAL_OPERAND:
case STATUS_FLOAT_DIVIDE_BY_ZERO: case STATUS_FLOAT_DIVIDE_BY_ZERO:
case STATUS_FLOAT_INEXACT_RESULT:
case STATUS_FLOAT_INVALID_OPERATION: case STATUS_FLOAT_INVALID_OPERATION:
case STATUS_FLOAT_OVERFLOW:
case STATUS_FLOAT_STACK_CHECK: 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: case STATUS_FLOAT_UNDERFLOW:
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_FLTUND;
break;
case STATUS_INTEGER_DIVIDE_BY_ZERO: case STATUS_INTEGER_DIVIDE_BY_ZERO:
si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_INTDIV;
break;
case STATUS_INTEGER_OVERFLOW: case STATUS_INTEGER_OVERFLOW:
sig = SIGFPE; si.si_signo = SIGFPE;
si.si_sigval.sival_int = FPE_INTOVF;
break; break;
case STATUS_ILLEGAL_INSTRUCTION: case STATUS_ILLEGAL_INSTRUCTION:
si.si_signo = SIGILL;
si.si_sigval.sival_int = ILL_ILLOPC;
break;
case STATUS_PRIVILEGED_INSTRUCTION: case STATUS_PRIVILEGED_INSTRUCTION:
si.si_signo = SIGILL;
si.si_sigval.sival_int = ILL_PRVOPC;
break;
case STATUS_NONCONTINUABLE_EXCEPTION: case STATUS_NONCONTINUABLE_EXCEPTION:
sig = SIGILL; si.si_signo = SIGILL;
si.si_sigval.sival_int = ILL_ILLADR;
break; break;
case STATUS_TIMEOUT: case STATUS_TIMEOUT:
sig = SIGALRM; si.si_signo = SIGALRM;
si.si_sigval.sival_int = 0;
break; break;
case STATUS_ACCESS_VIOLATION: case STATUS_ACCESS_VIOLATION:
@ -453,11 +479,13 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
case STATUS_NO_MEMORY: case STATUS_NO_MEMORY:
case STATUS_INVALID_DISPOSITION: case STATUS_INVALID_DISPOSITION:
case STATUS_STACK_OVERFLOW: case STATUS_STACK_OVERFLOW:
sig = SIGSEGV; si.si_signo = SIGSEGV;
si.si_sigval.sival_int = SEGV_MAPERR;
break; break;
case STATUS_CONTROL_C_EXIT: case STATUS_CONTROL_C_EXIT:
sig = SIGINT; si.si_signo = SIGINT;
si.si_sigval.sival_int = 0;
break; break;
case STATUS_INVALID_HANDLE: 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 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)) if (global_sigs[si.si_signo].sa_mask & SIGTOMASK (si.si_signo))
syscall_printf ("signal %d, masked %p", sig, global_sigs[sig].sa_mask); syscall_printf ("signal %d, masked %p", si.si_signo,
global_sigs[si.si_signo].sa_mask);
debug_printf ("In cygwin_except_handler calling %p", 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; DWORD *ebp = (DWORD *)in.Esp;
for (DWORD *bpend = (DWORD *) __builtin_frame_address (0); ebp > bpend; ebp--) 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] if (!myself->progname[0]
|| GetCurrentThreadId () == sigtid || GetCurrentThreadId () == sigtid
|| (void *) global_sigs[sig].sa_handler == (void *) SIG_DFL || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_DFL
|| (void *) global_sigs[sig].sa_handler == (void *) SIG_IGN || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_IGN
|| (void *) global_sigs[sig].sa_handler == (void *) SIG_ERR) || (void *) global_sigs[si.si_signo].sa_handler == (void *) SIG_ERR)
{ {
/* Print the exception to the console */ /* Print the exception to the console */
if (1) for (int i = 0; status_info[i].name; i++)
{ if (status_info[i].code == e.ExceptionCode)
for (int i = 0; status_info[i].name; i++) {
{ if (!myself->ppid_handle)
if (status_info[i].code == e.ExceptionCode) system_printf ("Exception: %s", status_info[i].name);
{ break;
if (!myself->ppid_handle) }
system_printf ("Exception: %s", status_info[i].name);
break;
}
}
}
/* Another exception could happen while tracing or while exiting. /* Another exception could happen while tracing or while exiting.
Only do this once. */ Only do this once. */
@ -529,11 +553,14 @@ handle_exceptions (EXCEPTION_RECORD *e0, void *frame, CONTEXT *in0, void *)
stackdump ((DWORD) ebp, 0, 1); 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); _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; return 1;
} }
#endif /* __i386__ */ #endif /* __i386__ */
@ -605,7 +632,14 @@ sig_handle_tty_stop (int sig)
{ {
pinfo parent (myself->ppid); pinfo parent (myself->ppid);
if (ISSTATE (parent, PID_NOCLDSTOP)) 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", sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p",
myself->pid, sig, myself->ppid_handle); myself->pid, sig, myself->ppid_handle);
@ -814,8 +848,8 @@ ctrl_c_handler (DWORD type)
{ {
if (type == CTRL_CLOSE_EVENT) if (type == CTRL_CLOSE_EVENT)
{ {
saw_close = true;
sig_send (NULL, SIGHUP); sig_send (NULL, SIGHUP);
saw_close = true;
return FALSE; return FALSE;
} }
if (!saw_close && type == CTRL_LOGOFF_EVENT) if (!saw_close && type == CTRL_LOGOFF_EVENT)
@ -849,7 +883,7 @@ ctrl_c_handler (DWORD type)
a CTRL_C_EVENT or CTRL_BREAK_EVENT. */ a CTRL_C_EVENT or CTRL_BREAK_EVENT. */
{ {
t->last_ctrl_c = GetTickCount (); t->last_ctrl_c = GetTickCount ();
kill (-myself->pid, SIGINT); killsys (-myself->pid, SIGINT);
t->last_ctrl_c = GetTickCount (); t->last_ctrl_c = GetTickCount ();
return TRUE; return TRUE;
} }
@ -884,9 +918,9 @@ set_signal_mask (sigset_t newmask, sigset_t oldmask)
} }
int __stdcall 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; DWORD stopped = myself->process_state & PID_STOPPED;
myself->stopsig = 0; myself->stopsig = 0;
@ -901,41 +935,56 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
} }
int rc = 1; int rc = 1;
bool insigwait_mask = tls ? sigismember (&tls->sigwait_mask, sig) : false;
bool special_case = ISSTATE (myself, PID_STOPPED) || main_vfork->pid; sigproc_printf ("signal %d processing", si.si_signo);
bool masked = sigismember (&mask, sig); struct sigaction thissig = global_sigs[si.si_signo];
if (sig != SIGKILL && sig != SIGSTOP
&& (special_case || main_vfork->pid || masked || insigwait_mask myself->rusage_self.ru_nsignals++;
|| (tls && sigismember (&tls->sigmask, sig))))
if (si.si_signo == SIGKILL)
goto exit_sig;
if ( si.si_signo == SIGSTOP)
{ {
sigproc_printf ("signal %d blocked", sig); sig_clear (SIGCONT);
if ((!special_case && !masked) goto stop;
&& (insigwait_mask || (tls = _threadinfo::find_tls (sig)) != NULL)) }
goto thread_specific;
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; rc = -1;
goto done; 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; void *handler;
handler = (void *) thissig.sa_handler; handler = (void *) thissig.sa_handler;
myself->rusage_self.ru_nsignals++; /* Clear pending SIGCONT on stop signals */
if (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU)
if (sig == SIGKILL) sig_clear (SIGCONT);
goto exit_sig;
if (sig == SIGSTOP)
goto stop;
#if 0 #if 0
char sigmsg[24]; char sigmsg[24];
__small_sprintf (sigmsg, "cygwin: signal %d\n", sig); __small_sprintf (sigmsg, "cygwin: signal %d\n", si.si_signo);
OutputDebugString (sigmsg); OutputDebugString (sigmsg);
#endif #endif
@ -943,14 +992,14 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
{ {
if (insigwait_mask) if (insigwait_mask)
goto thread_specific; goto thread_specific;
if (sig == SIGCHLD || sig == SIGIO || sig == SIGCONT || sig == SIGWINCH if (si.si_signo == SIGCHLD || si.si_signo == SIGIO || si.si_signo == SIGCONT || si.si_signo == SIGWINCH
|| sig == SIGURG) || si.si_signo == SIGURG)
{ {
sigproc_printf ("default signal %d ignored", sig); sigproc_printf ("default signal %d ignored", si.si_signo);
goto done; 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 stop;
goto exit_sig; goto exit_sig;
@ -958,7 +1007,7 @@ sig_handle (int sig, sigset_t mask, int pid, _threadinfo *tls)
if (handler == (void *) SIG_IGN) if (handler == (void *) SIG_IGN)
{ {
sigproc_printf ("signal %d ignored", sig); sigproc_printf ("signal %d ignored", si.si_signo);
goto done; goto done;
} }
@ -973,34 +1022,38 @@ stop:
goto done; goto done;
handler = (void *) sig_handle_tty_stop; handler = (void *) sig_handle_tty_stop;
thissig = global_sigs[SIGSTOP]; thissig = global_sigs[SIGSTOP];
goto dosig1;
dosig: dosig:
tls->set_siginfo (this);
dosig1:
/* Dispatch to the appropriate function. */ /* Dispatch to the appropriate function. */
sigproc_printf ("signal %d, about to call %p", sig, handler); sigproc_printf ("signal %d, about to call %p", si.si_signo, handler);
rc = setup_handler (sig, handler, thissig, tls ?: _main_tls); rc = setup_handler (si.si_signo, handler, thissig, tls);
done: done:
sigproc_printf ("returning %d", rc); sigproc_printf ("returning %d", rc);
return rc; return rc;
thread_specific: thread_specific:
tls->sig = sig; tls->sig = si.si_signo;
tls->set_siginfo (this);
sigproc_printf ("releasing sigwait for thread"); sigproc_printf ("releasing sigwait for thread");
SetEvent (tls->event); SetEvent (tls->event);
goto done; goto done;
exit_sig: exit_sig:
if (sig == SIGQUIT || sig == SIGABRT) if (si.si_signo == SIGQUIT || si.si_signo == SIGABRT)
{ {
CONTEXT c; CONTEXT c;
c.ContextFlags = CONTEXT_FULL; c.ContextFlags = CONTEXT_FULL;
GetThreadContext (hMainThread, &c); GetThreadContext (hMainThread, &c);
if (!try_to_debug ()) if (!try_to_debug ())
stackdump (c.Ebp, 1, 1); stackdump (c.Ebp, 1, 1);
sig |= 0x80; si.si_signo |= 0x80;
} }
sigproc_printf ("signal %d, about to call do_exit", sig); sigproc_printf ("signal %d, about to call do_exit", si.si_signo);
signal_exit (sig); signal_exit (si.si_signo);
/* Never returns */ /* Never returns */
} }

View File

@ -87,6 +87,10 @@ tty_min::kill_pgrp (int sig)
{ {
int killself = 0; int killself = 0;
winpids pids ((DWORD) PID_MAP_RW); 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++) for (unsigned i = 0; i < pids.npids; i++)
{ {
_pinfo *p = pids[i]; _pinfo *p = pids[i];
@ -95,10 +99,10 @@ tty_min::kill_pgrp (int sig)
if (p == myself) if (p == myself)
killself++; killself++;
else else
(void) sig_send (p, sig); (void) sig_send (p, si);
} }
if (killself) if (killself)
sig_send (myself, sig); sig_send (myself, si);
} }
bg_check_types 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 /* Don't raise a SIGTT* signal if we have already been interrupted
by another signal. */ by another signal. */
if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0) 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; return bg_signalled;
setEIO: setEIO:

View File

@ -1109,7 +1109,7 @@ fhandler_tty_slave::ioctl (unsigned int cmd, void *arg)
get_ttyp ()->arg.winsize = *(struct winsize *) arg; get_ttyp ()->arg.winsize = *(struct winsize *) arg;
SetEvent (ioctl_request_event); SetEvent (ioctl_request_event);
get_ttyp ()->winsize = *(struct winsize *) arg; get_ttyp ()->winsize = *(struct winsize *) arg;
kill (-get_ttyp ()->getpgid (), SIGWINCH); killsys (-get_ttyp ()->getpgid (), SIGWINCH);
if (ioctl_done_event) if (ioctl_done_event)
WaitForSingleObject (ioctl_done_event, INFINITE); 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.ws_col != ((struct winsize *) arg)->ws_col)
{ {
get_ttyp ()->winsize = *(struct winsize *) arg; get_ttyp ()->winsize = *(struct winsize *) arg;
kill (-get_ttyp ()->getpgid (), SIGWINCH); killsys (-get_ttyp ()->getpgid (), SIGWINCH);
} }
break; break;
case FIONBIO: case FIONBIO:

View File

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

View File

@ -169,10 +169,12 @@ _sigdelayed:
pushl $tls::newmask(%ebx) # newmask - eaten by set_process_mask pushl $tls::newmask(%ebx) # newmask - eaten by set_process_mask
call _set_process_mask\@4 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 movl \$0,$tls::sig(%ebx) # zero the signal number as a
# flag to the signal handler thread # flag to the signal handler thread
# that it is ok to set up sigsave # that it is ok to set up sigsave
popl %ebx 4: popl %ebx
jmp *%ebx jmp *%ebx
EOF 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 #ifndef _CYGWIN_SIGNAL_H
#define _CYGWIN_SIGNAL_H #define _CYGWIN_SIGNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#if 0 #if 0
struct ucontext struct ucontext
{ {
@ -8,7 +22,7 @@ struct ucontext
void *uc_link; void *uc_link;
stack_t uc_stack; stack_t uc_stack;
struct sigcontext uc_mcontext; struct sigcontext uc_mcontext;
sigset_t uc_sigmask; sigset_t uc_sigmask;
}; };
#endif #endif
@ -18,49 +32,55 @@ typedef union sigval
void *sival_ptr; /* pointer signal value */ void *sival_ptr; /* pointer signal value */
} sigval_t; } 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) #pragma pack(push,4)
typedef struct typedef struct
{ {
int si_signo; /* signal number */ int si_signo; /* signal number */
int si_errno; /* errno associated with signal */
int si_code; /* signal code */ 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 union
{ {
int __pad[128]; /* plan for future growth */ __uint32_t __pad[32]; /* plan for future growth */
union union
{ {
/* timers */ /* timers */
struct struct
{ {
unsigned int si_tid; /* timer id */ union
unsigned int si_overrun; /* overrun count */ {
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 struct
{ {
pid_t si_pid2; /* which child */ int si_status; /* exit code */
uid_t si_uid2; /* sender's uid */
int si_status; /* exit code */
clock_t si_utime; /* user time */ clock_t si_utime; /* user time */
clock_t si_stime; /* system time */ clock_t si_stime; /* system time */
}; };
/* core dumping signals */ /* core dumping signals */
struct void *si_addr; /* faulting address */
{
void *si_addr; /* faulting address */
};
}; };
} siginfo_t; } siginfo_t;
#pragma pack(pop) #pragma pack(pop)
@ -77,7 +97,7 @@ enum
unimplemented) */ unimplemented) */
SI_KERNEL, /* sent by system */ SI_KERNEL, /* sent by system */
ILL_ILLOP, /* illegal opcode */ ILL_ILLOPC, /* illegal opcode */
ILL_ILLOPN, /* illegal operand */ ILL_ILLOPN, /* illegal operand */
ILL_ILLADR, /* illegal addressing mode */ ILL_ILLADR, /* illegal addressing mode */
ILL_ILLTRP, /* illegal trap*/ ILL_ILLTRP, /* illegal trap*/
@ -110,15 +130,6 @@ enum
CLD_CONTINUED /* stopped child has continued */ 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 enum
{ {
SIGEV_SIGNAL = 0, /* a queued signal, with an application SIGEV_SIGNAL = 0, /* a queued signal, with an application
@ -133,7 +144,7 @@ enum
typedef void (*_sig_func_ptr)(int); typedef void (*_sig_func_ptr)(int);
struct sigaction struct sigaction
{ {
union union
{ {
@ -188,4 +199,10 @@ struct sigaction
#define SIGUSR1 30 /* user defined signal 1 */ #define SIGUSR1 30 /* user defined signal 1 */
#define SIGUSR2 31 /* user defined signal 2 */ #define SIGUSR2 31 /* user defined signal 2 */
#define NSIG 32 /* signal 0 implied */ #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*/ #endif /*_CYGWIN_SIGNAL_H*/

View File

@ -233,12 +233,14 @@ details. */
106: Export flock. 106: Export flock.
107: Export fcntl64. 107: Export fcntl64.
108: Remove unused (hopefully) reent_data export. 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 */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0 #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 /* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible 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 static int
kill_worker (pid_t pid, int sig) kill_worker (pid_t pid, siginfo_t& si)
{ {
sig_dispatch_pending (); sig_dispatch_pending ();
int res = 0; int res = 0;
pinfo dest (pid); pinfo dest (pid);
BOOL sendSIGCONT; bool sendSIGCONT;
if (!dest) if (!dest)
{ {
@ -196,25 +196,32 @@ kill_worker (pid_t pid, int sig)
return -1; return -1;
} }
if ((sendSIGCONT = (sig < 0))) if ((sendSIGCONT = (si.si_signo < 0)))
sig = -sig; si.si_signo = -si.si_signo;
DWORD process_state = dest->process_state; DWORD process_state = dest->process_state;
if (sig == 0) if (si.si_signo == 0)
{ {
res = proc_exists (dest) ? 0 : -1; res = proc_exists (dest) ? 0 : -1;
if (res < 0) if (res < 0)
set_errno (ESRCH); set_errno (ESRCH);
} }
else if ((res = sig_send (dest, sig))) else if ((res = sig_send (dest, si)))
{ {
sigproc_printf ("%d = sig_send, %E ", res); sigproc_printf ("%d = sig_send, %E ", res);
res = -1; res = -1;
} }
else if (sendSIGCONT) 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; return res;
} }
@ -224,35 +231,54 @@ raise (int sig)
return kill (myself->pid, sig); return kill (myself->pid, sig);
} }
int static int
kill (pid_t pid, int sig) 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 */ /* check that sig is in right range */
if (sig < 0 || sig >= NSIG) if (si.si_signo < 0 || si.si_signo >= NSIG)
{ {
set_errno (EINVAL); set_errno (EINVAL);
syscall_printf ("signal %d out of range", sig); syscall_printf ("signal %d out of range", si.si_signo);
return -1; return -1;
} }
/* Silently ignore stop signals from a member of orphaned process group. /* Silently ignore stop signals from a member of orphaned process group.
FIXME: Why??? */ FIXME: Why??? */
if (ISSTATE (myself, PID_ORPHANED) && if (ISSTATE (myself, PID_ORPHANED) &&
(sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU)) (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU))
sig = 0; 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 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 res = 0;
int found = 0; int found = 0;
int killself = 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); winpids pids ((DWORD) PID_MAP_RW);
for (unsigned i = 0; i < pids.npids; i++) 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? */ /* Is it a process we want to kill? */
if ((pid == 0 && (p->pgid != myself->pgid || p->ctty != myself->ctty)) || if ((pid == 0 && (p->pgid != myself->pgid || p->ctty != myself->ctty)) ||
(pid > 1 && p->pgid != pid) || (pid > 1 && p->pgid != pid) ||
(sig < 0 && NOTSTATE (p, PID_STOPPED))) (si.si_signo < 0 && NOTSTATE (p, PID_STOPPED)))
continue; continue;
sigproc_printf ("killing pid %d, pgrp %d, p->ctty %d, myself->ctty %d", sigproc_printf ("killing pid %d, pgrp %d, p->ctty %d, myself->ctty %d",
p->pid, p->pgid, p->ctty, myself->ctty); p->pid, p->pgid, p->ctty, myself->ctty);
if (p == myself) if (p == myself)
killself++; killself++;
else if (kill_worker (p->pid, sig)) else if (kill_worker (p->pid, si))
res = -1; res = -1;
found++; found++;
} }
if (killself && kill_worker (myself->pid, sig)) if (killself && kill_worker (myself->pid, si))
res = -1; res = -1;
if (!found) if (!found)
@ -284,7 +310,7 @@ kill_pgrp (pid_t pid, int sig)
set_errno (ESRCH); set_errno (ESRCH);
res = -1; res = -1;
} }
syscall_printf ("%d = kill (%d, %d)", res, pid, sig); syscall_printf ("%d = kill (%d, %d)", res, pid, si.si_signo);
return res; return res;
} }
@ -452,12 +478,21 @@ siginterrupt (int sig, int flag)
return sigaction (sig, &act, NULL); 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 extern "C" int
sigwait (const sigset_t *set, int *sig) sigwaitinfo (const sigset_t *set, siginfo_t *info)
{ {
pthread_testcancel (); 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) if (!_my_tls.event)
{ {
__seterrno (); __seterrno ();
@ -466,16 +501,22 @@ sigwait (const sigset_t *set, int *sig)
_my_tls.sigwait_mask = *set; _my_tls.sigwait_mask = *set;
int res;
switch (WaitForSingleObject (_my_tls.event, INFINITE)) switch (WaitForSingleObject (_my_tls.event, INFINITE))
{ {
case WAIT_OBJECT_0: case WAIT_OBJECT_0:
CloseHandle (_my_tls.event); res = _my_tls.infodata.si_signo;
_my_tls.event = NULL; sigproc_printf ("returning sig %d", res);
*sig = InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0); if (info)
*info = _my_tls.infodata;
break; break;
default: default:
__seterrno (); __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 #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 class pending_signals
{ {
sigelem sigs[NSIG + 1]; sigpacket sigs[NSIG + 1];
sigelem start; sigpacket start;
sigelem *end; sigpacket *end;
sigelem *prev; sigpacket *prev;
sigelem *curr; sigpacket *curr;
int empty; int empty;
public: public:
void reset () {curr = &start; prev = &start;} void reset () {curr = &start; prev = &start;}
void add (int sig, int pid, _threadinfo *tls); void add (sigpacket&);
void del (); void del ();
sigelem *next (); sigpacket *next ();
friend int __stdcall sig_dispatch_pending (); friend int __stdcall sig_dispatch_pending ();
}; };
struct sigpacket
{
int sig;
pid_t pid;
HANDLE wakeup;
sigset_t *mask;
_threadinfo *tls;
};
static pending_signals sigqueue; static pending_signals sigqueue;
struct sigaction *global_sigs; struct sigaction *global_sigs;
@ -563,9 +544,9 @@ sig_clear (int target_sig)
else else
{ {
sigqueue.reset (); sigqueue.reset ();
sigelem *q; sigpacket *q;
while ((q = sigqueue.next ())) while ((q = sigqueue.next ()))
if (q->sig == target_sig) if (q->si.si_signo == target_sig)
{ {
sigqueue.del (); sigqueue.del ();
break; break;
@ -670,13 +651,22 @@ sigproc_terminate (void)
return; 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 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; int rc = 1;
bool its_me; 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? */ if (!proc_can_be_signalled (p)) /* Is the process accepting messages? */
{ {
sigproc_printf ("invalid pid %d(%x), signal %d", sigproc_printf ("invalid pid %d(%x), signal %d",
p->pid, p->process_state, sig); p->pid, p->process_state, si.si_signo);
goto out; 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) if (its_me)
{ {
@ -740,16 +730,21 @@ sig_send (_pinfo *p, int sig, void *tls)
sigset_t pending; sigset_t pending;
if (!its_me) if (!its_me)
pack.mask = NULL; pack.mask = NULL;
else if (sig == __SIGPENDING) else if (si.si_signo == __SIGPENDING)
pack.mask = &pending; pack.mask = &pending;
else if (sig == __SIGFLUSH || sig > 0) else if (si.si_signo == __SIGFLUSH || si.si_signo > 0)
pack.mask = &myself->getsigmask (); pack.mask = &myself->getsigmask ();
else else
pack.mask = NULL; 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.pid = myself->pid;
pack.tls = (_threadinfo *) tls; pack.tls = (_threadinfo *) tls;
pack.mask_storage = 0;
DWORD nb; DWORD nb;
if (!WriteFile (sendsig, &pack, sizeof (pack), &nb, NULL) || nb != sizeof (pack)) 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"); sigproc_printf ("I'm going away now");
else else
system_printf ("error sending signal %d to pid %d, pipe handle %p, %E", 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; goto out;
} }
@ -787,7 +782,8 @@ sig_send (_pinfo *p, int sig, void *tls)
else else
{ {
rc = WAIT_OBJECT_0; 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) if (!its_me)
ForceCloseHandle (sendsig); ForceCloseHandle (sendsig);
} }
@ -798,7 +794,7 @@ sig_send (_pinfo *p, int sig, void *tls)
{ {
if (!no_signals_available ()) if (!no_signals_available ())
system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E", system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E",
sig, rc); si.si_signo, rc);
set_errno (ENOSYS); set_errno (ENOSYS);
rc = -1; rc = -1;
} }
@ -807,13 +803,13 @@ sig_send (_pinfo *p, int sig, void *tls)
call_signal_handler_now (); call_signal_handler_now ();
out: out:
if (sig != __SIGPENDING) if (si.si_signo != __SIGPENDING)
/* nothing */; /* nothing */;
else if (!rc) else if (!rc)
rc = (int) pending; rc = (int) pending;
else else
rc = SIG_BAD_MASK; 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; return rc;
} }
@ -1009,20 +1005,20 @@ talktome ()
has been handled, as per POSIX. */ has been handled, as per POSIX. */
void 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) for (se = start.next; se; se = se->next)
if (se->sig == sig) if (se->si.si_signo == pack.si.si_signo)
return; return;
while (sigs[empty].sig) while (sigs[empty].si.si_signo)
if (++empty == NSIG) if (++empty == NSIG)
empty = 0; empty = 0;
se = sigs + empty; se = sigs + empty;
se->sig = sig; *se = pack;
se->mask_storage = *(pack.mask);
se->mask = &se->mask_storage;
se->next = NULL; se->next = NULL;
se->tls = tls;
se->pid = pid;
if (end) if (end)
end->next = se; end->next = se;
end = se; end = se;
@ -1034,9 +1030,9 @@ pending_signals::add (int sig, int pid, _threadinfo *tls)
void void
pending_signals::del () pending_signals::del ()
{ {
sigelem *next = curr->next; sigpacket *next = curr->next;
prev->next = next; prev->next = next;
curr->sig = 0; curr->si.si_signo = 0;
#ifdef DEBUGGING #ifdef DEBUGGING
curr->next = NULL; curr->next = NULL;
#endif #endif
@ -1046,10 +1042,10 @@ pending_signals::del ()
curr = next; curr = next;
} }
sigelem * sigpacket *
pending_signals::next () pending_signals::next ()
{ {
sigelem *res; sigpacket *res;
prev = curr; prev = curr;
if (!curr || !(curr = curr->next)) if (!curr || !(curr = curr->next))
res = NULL; res = NULL;
@ -1125,7 +1121,7 @@ wait_sig (VOID *self)
continue; continue;
} }
if (!pack.sig) if (!pack.si.si_signo)
{ {
#ifdef DEBUGGING #ifdef DEBUGGING
system_printf ("zero signal?"); system_printf ("zero signal?");
@ -1140,8 +1136,8 @@ wait_sig (VOID *self)
pack.mask = &dummy_mask; pack.mask = &dummy_mask;
} }
sigelem *q; sigpacket *q;
switch (pack.sig) switch (pack.si.si_signo)
{ {
case __SIGCOMMUNE: case __SIGCOMMUNE:
talktome (); talktome ();
@ -1154,30 +1150,30 @@ wait_sig (VOID *self)
unsigned bit; unsigned bit;
sigqueue.reset (); sigqueue.reset ();
while ((q = sigqueue.next ())) while ((q = sigqueue.next ()))
if (myself->getsigmask () & (bit = SIGTOMASK (q->sig))) if (myself->getsigmask () & (bit = SIGTOMASK (q->si.si_signo)))
*pack.mask |= bit; *pack.mask |= bit;
break; break;
case __SIGFLUSH: case __SIGFLUSH:
sigqueue.reset (); sigqueue.reset ();
while ((q = sigqueue.next ())) while ((q = sigqueue.next ()))
if (sig_handle (q->sig, *pack.mask, q->pid, q->tls) > 0) if (q->process () > 0)
sigqueue.del (); sigqueue.del ();
break; break;
default: default:
if (pack.sig < 0) if (pack.si.si_signo < 0)
sig_clear (-pack.sig); sig_clear (-pack.si.si_signo);
else else
{ {
int sigres = sig_handle (pack.sig, *pack.mask, pack.pid, pack.tls); int sigres = pack.process ();
if (sigres <= 0) if (sigres <= 0)
{ {
#ifdef DEBUGGING2 #ifdef DEBUGGING2
if (!sigres) if (!sigres)
system_printf ("Failed to arm signal %d from pid %d", pack.sig, pack.pid); system_printf ("Failed to arm signal %d from pid %d", pack.sig, pack.pid);
#endif #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); proc_subproc (PROC_CLEARWAIT, 0);
} }
break; break;
@ -1245,6 +1241,20 @@ wait_subproc (VOID *)
rc -= WAIT_OBJECT_0; rc -= WAIT_OBJECT_0;
if (rc-- != 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); rc = proc_subproc (PROC_CHILDTERMINATED, rc);
if (!proc_loop_wait) // Don't bother if wait_subproc is if (!proc_loop_wait) // Don't bother if wait_subproc is
break; // exiting break; // exiting
@ -1253,7 +1263,7 @@ wait_subproc (VOID *)
to avoid the proc_subproc lock since the signal thread will eventually to avoid the proc_subproc lock since the signal thread will eventually
be calling proc_subproc and could unnecessarily block. */ be calling proc_subproc and could unnecessarily block. */
if (rc) if (rc)
sig_send (myself_nowait, SIGCHLD); sig_send (myself_nowait, si);
} }
sigproc_printf ("looping"); sigproc_printf ("looping");
} }

View File

@ -48,6 +48,21 @@ typedef struct struct_waitq
HANDLE thread_ev; HANDLE thread_ev;
} waitq; } 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 signal_arrived;
extern HANDLE sigCONT; 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" void __stdcall reset_signal_arrived ();
extern "C" int __stdcall call_signal_handler_now (); 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_clear (int) __attribute__ ((regparm (1)));
void __stdcall sig_set_pending (int) __attribute__ ((regparm (1))); void __stdcall sig_set_pending (int) __attribute__ ((regparm (1)));
int __stdcall handle_sigsuspend (sigset_t); int __stdcall handle_sigsuspend (sigset_t);
@ -78,12 +90,16 @@ void __stdcall subproc_init ();
void __stdcall sigproc_terminate (); void __stdcall sigproc_terminate ();
bool __stdcall proc_exists (_pinfo *) __attribute__ ((regparm(1))); bool __stdcall proc_exists (_pinfo *) __attribute__ ((regparm(1)));
bool __stdcall pid_exists (pid_t) __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_fork ();
void __stdcall signal_fixup_after_exec (); void __stdcall signal_fixup_after_exec ();
void __stdcall wait_for_sigthread (); void __stdcall wait_for_sigthread ();
void __stdcall sigalloc (); void __stdcall sigalloc ();
int kill_pgrp (pid_t, siginfo_t&);
int killsys (pid_t, int);
extern char myself_nowait_dummy[]; extern char myself_nowait_dummy[];
extern struct sigaction *global_sigs; 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. */ ensure we don't leave any such files lying around. */
void __stdcall void __stdcall
close_all_files (void) close_all_files ()
{ {
cygheap->fdtab.lock (); cygheap->fdtab.lock ();

View File

@ -2736,7 +2736,12 @@ pthread_kill (pthread_t thread, int sig)
if (!pthread::is_good_object (&thread)) if (!pthread::is_good_object (&thread))
return EINVAL; 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 // unlock myself
return rval; 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 /* 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. This file is part of Cygwin.
@ -15,6 +15,7 @@ details. */
#include <utime.h> #include <utime.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <pthread.h>
#include "cygerrno.h" #include "cygerrno.h"
#include "security.h" #include "security.h"
#include "path.h" #include "path.h"
@ -22,6 +23,9 @@ details. */
#include "pinfo.h" #include "pinfo.h"
#include "hires.h" #include "hires.h"
#include "cygtls.h" #include "cygtls.h"
#include "cygthread.h"
#include "sigproc.h"
#include "sync.h"
#define FACTOR (0x19db1ded53e8000LL) #define FACTOR (0x19db1ded53e8000LL)
#define NSPERSEC 10000000LL #define NSPERSEC 10000000LL
@ -612,7 +616,8 @@ hires_us::usecs (bool justdelta)
// FIXME: Use round() here? // FIXME: Use round() here?
now.QuadPart = (LONGLONG) (freq * (double) (now.QuadPart - primed_pc.QuadPart)); 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 UINT
@ -657,3 +662,21 @@ hires_ms::usecs (bool justdelta)
LONGLONG res = initime_us.QuadPart + ((LONGLONG) (now - initime_ms) * 1000); LONGLONG res = initime_us.QuadPart + ((LONGLONG) (now - initime_ms) * 1000);
return res; 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. //;# autogenerated: Do not edit.
//; $tls::func = -4076; //; $tls::func = -3704;
//; $tls::saved_errno = -4072; //; $tls::saved_errno = -3700;
//; $tls::sa_flags = -4068; //; $tls::sa_flags = -3696;
//; $tls::oldmask = -4064; //; $tls::oldmask = -3692;
//; $tls::newmask = -4060; //; $tls::newmask = -3688;
//; $tls::event = -4056; //; $tls::event = -3684;
//; $tls::errno_addr = -4052; //; $tls::errno_addr = -3680;
//; $tls::initialized = -4048; //; $tls::initialized = -3676;
//; $tls::sigmask = -4044; //; $tls::sigmask = -3672;
//; $tls::sigwait_mask = -4040; //; $tls::sigwait_mask = -3668;
//; $tls::sigwait_info = -4036; //; $tls::sigwait_info = -3664;
//; $tls::infodata = -4032; //; $tls::threadkill = -3660;
//; $tls::infodata = -3656;
//; $tls::tid = -3508; //; $tls::tid = -3508;
//; $tls::local_clib = -3504; //; $tls::local_clib = -3504;
//; $tls::locals = -2576; //; $tls::locals = -2576;
@ -23,18 +24,19 @@
//; $tls::padding = 0; //; $tls::padding = 0;
//; __DATA__ //; __DATA__
#define tls_func (-4076) #define tls_func (-3704)
#define tls_saved_errno (-4072) #define tls_saved_errno (-3700)
#define tls_sa_flags (-4068) #define tls_sa_flags (-3696)
#define tls_oldmask (-4064) #define tls_oldmask (-3692)
#define tls_newmask (-4060) #define tls_newmask (-3688)
#define tls_event (-4056) #define tls_event (-3684)
#define tls_errno_addr (-4052) #define tls_errno_addr (-3680)
#define tls_initialized (-4048) #define tls_initialized (-3676)
#define tls_sigmask (-4044) #define tls_sigmask (-3672)
#define tls_sigwait_mask (-4040) #define tls_sigwait_mask (-3668)
#define tls_sigwait_info (-4036) #define tls_sigwait_info (-3664)
#define tls_infodata (-4032) #define tls_threadkill (-3660)
#define tls_infodata (-3656)
#define tls_tid (-3508) #define tls_tid (-3508)
#define tls_local_clib (-3504) #define tls_local_clib (-3504)
#define tls_locals (-2576) #define tls_locals (-2576)

View File

@ -219,7 +219,7 @@ void uinfo_init (void);
void events_init (void); void events_init (void);
void events_terminate (void); void events_terminate (void);
void __stdcall close_all_files (void); void __stdcall close_all_files ();
/* Invisible window initialization/termination. */ /* Invisible window initialization/termination. */
HWND __stdcall gethwnd (void); HWND __stdcall gethwnd (void);
@ -318,10 +318,6 @@ int cygwin_select (int , fd_set *, fd_set *, fd_set *,
struct timeval *to); struct timeval *to);
int cygwin_gethostname (char *__name, size_t __len); 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 DWORD binmode;
extern char _data_start__, _data_end__, _bss_start__, _bss_end__; extern char _data_start__, _data_end__, _bss_start__, _bss_end__;
extern void (*__CTOR_LIST__) (void); extern void (*__CTOR_LIST__) (void);