* 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:
parent
49fec4c011
commit
f6936c48f3
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 *)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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*/
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 (¬ify_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 = ⁢
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue