* exceptions.cc (exception::handle): Drop abbreviation for "exception" since I
never remember what it stands for. (sig_handle_tty_stop): Remove obsolete call to sig_handle_tty_stop. (_cygtls::call_signal_handler): Rework to grab signal information from _main_tls if none is set for _my_tls. Try harder to keep thread locked. (reset_signal_arrived): Delete. * fhandler.cc (fhandler_base_overlapped::wait_overlapped): Use new cygWFMO call to wait for an event + standard cygwin stuff. Modify debug output to acccomodate new function. * fhandler_console.cc (fhandler_console::read): Replace WaitForMultipleObjects with cygWFMO. * fhandler_socket.cc (get_inet_addr): Add comment. * gendef (_sigdelayed): Remove call to reset_signal_arrived. * sigproc.cc (_cygtls::signal_exit): Don't close my_readsig here unless we're in the signal thread. (create_signal_arrived): Create signal_arrived as auto-reset so that only one thread is woken when a signal arrives. * sigproc.h (cygWFMO): New function. (reset_signal_arrived): Delete declaration.
This commit is contained in:
parent
69864e48cb
commit
8f937028d9
|
@ -1,3 +1,26 @@
|
||||||
|
2011-12-04 Christopher Faylor <me.cygwin2011@cgf.cx>
|
||||||
|
|
||||||
|
* exceptions.cc (exception::handle): Drop abbreviation for "exception"
|
||||||
|
since I never remember what it stands for.
|
||||||
|
(sig_handle_tty_stop): Remove obsolete call to sig_handle_tty_stop.
|
||||||
|
(_cygtls::call_signal_handler): Rework to grab signal information from
|
||||||
|
_main_tls if none is set for _my_tls. Try harder to keep thread
|
||||||
|
locked.
|
||||||
|
(reset_signal_arrived): Delete.
|
||||||
|
* fhandler.cc (fhandler_base_overlapped::wait_overlapped): Use new
|
||||||
|
cygWFMO call to wait for an event + standard cygwin stuff. Modify
|
||||||
|
debug output to acccomodate new function.
|
||||||
|
* fhandler_console.cc (fhandler_console::read): Replace
|
||||||
|
WaitForMultipleObjects with cygWFMO.
|
||||||
|
* fhandler_socket.cc (get_inet_addr): Add comment.
|
||||||
|
* gendef (_sigdelayed): Remove call to reset_signal_arrived.
|
||||||
|
* sigproc.cc (_cygtls::signal_exit): Don't close my_readsig here unless
|
||||||
|
we're in the signal thread.
|
||||||
|
(create_signal_arrived): Create signal_arrived as auto-reset so that only
|
||||||
|
one thread is woken when a signal arrives.
|
||||||
|
* sigproc.h (cygWFMO): New function.
|
||||||
|
(reset_signal_arrived): Delete declaration.
|
||||||
|
|
||||||
2011-12-03 Christopher Faylor <me.cygwin2011@cgf.cx>
|
2011-12-03 Christopher Faylor <me.cygwin2011@cgf.cx>
|
||||||
|
|
||||||
* mmap.cc (mlock): Add standard syscall return value debugging output.
|
* mmap.cc (mlock): Add standard syscall return value debugging output.
|
||||||
|
|
|
@ -600,7 +600,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in, void
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_printf ("In cygwin_except_handler exc %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
|
debug_printf ("In cygwin_except_handler exception %p at %p sp %p", e->ExceptionCode, in->Eip, in->Esp);
|
||||||
debug_printf ("In cygwin_except_handler signal %d at %p", si.si_signo, in->Eip);
|
debug_printf ("In cygwin_except_handler signal %d at %p", si.si_signo, in->Eip);
|
||||||
|
|
||||||
bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo));
|
bool masked = !!(me.sigmask & SIGTOMASK (si.si_signo));
|
||||||
|
@ -755,7 +755,6 @@ sig_handle_tty_stop (int sig)
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
case WAIT_OBJECT_0 + 1:
|
case WAIT_OBJECT_0 + 1:
|
||||||
reset_signal_arrived ();
|
|
||||||
myself->stopsig = SIGCONT;
|
myself->stopsig = SIGCONT;
|
||||||
myself->alert_parent (SIGCONT);
|
myself->alert_parent (SIGCONT);
|
||||||
break;
|
break;
|
||||||
|
@ -1325,25 +1324,42 @@ events_terminate ()
|
||||||
int
|
int
|
||||||
_cygtls::call_signal_handler ()
|
_cygtls::call_signal_handler ()
|
||||||
{
|
{
|
||||||
int this_sa_flags = 0;
|
int this_sa_flags = SA_RESTART;
|
||||||
/* Call signal handler. */
|
while (1)
|
||||||
while (sig && func)
|
|
||||||
{
|
{
|
||||||
lock ();
|
lock ();
|
||||||
|
if (sig)
|
||||||
|
pop ();
|
||||||
|
else if (this != _main_tls)
|
||||||
|
{
|
||||||
|
_main_tls->lock ();
|
||||||
|
if (_main_tls->sig)
|
||||||
|
{
|
||||||
|
sig = _main_tls->sig;
|
||||||
|
sa_flags = _main_tls->sa_flags;
|
||||||
|
func = _main_tls->func;
|
||||||
|
infodata = _main_tls->infodata;
|
||||||
|
_main_tls->pop ();
|
||||||
|
_main_tls->sig = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
_main_tls->unlock ();
|
||||||
|
}
|
||||||
|
if (!sig)
|
||||||
|
break;
|
||||||
|
|
||||||
this_sa_flags = sa_flags;
|
this_sa_flags = sa_flags;
|
||||||
int thissig = sig;
|
int thissig = sig;
|
||||||
void (*thisfunc) (int) = func;
|
void (*thisfunc) (int) = func;
|
||||||
|
|
||||||
pop ();
|
|
||||||
reset_signal_arrived ();
|
|
||||||
sigset_t this_oldmask = set_process_mask_delta ();
|
sigset_t this_oldmask = set_process_mask_delta ();
|
||||||
int this_errno = saved_errno;
|
int this_errno = saved_errno;
|
||||||
sig = 0;
|
sig = 0;
|
||||||
unlock (); // make sure synchronized
|
unlock (); // make sure synchronized
|
||||||
incyg = 0;
|
|
||||||
if (!(this_sa_flags & SA_SIGINFO))
|
if (!(this_sa_flags & SA_SIGINFO))
|
||||||
{
|
{
|
||||||
void (*sigfunc) (int) = thisfunc;
|
void (*sigfunc) (int) = thisfunc;
|
||||||
|
incyg = false;
|
||||||
sigfunc (thissig);
|
sigfunc (thissig);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1351,27 +1367,19 @@ _cygtls::call_signal_handler ()
|
||||||
siginfo_t thissi = infodata;
|
siginfo_t thissi = infodata;
|
||||||
void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) thisfunc;
|
void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) thisfunc;
|
||||||
/* no ucontext_t information provided yet */
|
/* no ucontext_t information provided yet */
|
||||||
|
incyg = false;
|
||||||
sigact (thissig, &thissi, NULL);
|
sigact (thissig, &thissi, NULL);
|
||||||
}
|
}
|
||||||
incyg = 1;
|
incyg = true;
|
||||||
set_signal_mask (this_oldmask, _my_tls.sigmask);
|
set_signal_mask (this_oldmask, _my_tls.sigmask);
|
||||||
if (this_errno >= 0)
|
if (this_errno >= 0)
|
||||||
set_errno (this_errno);
|
set_errno (this_errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock ();
|
||||||
return this_sa_flags & SA_RESTART;
|
return this_sa_flags & SA_RESTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void __stdcall
|
|
||||||
reset_signal_arrived ()
|
|
||||||
{
|
|
||||||
// NEEDED? WaitForSingleObject (signal_arrived, 10);
|
|
||||||
ResetEvent (signal_arrived);
|
|
||||||
sigproc_printf ("reset signal_arrived");
|
|
||||||
if (_my_tls.stackptr > _my_tls.stack)
|
|
||||||
debug_printf ("stackptr[-1] %p", _my_tls.stackptr[-1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_cygtls::copy_context (CONTEXT *c)
|
_cygtls::copy_context (CONTEXT *c)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1925,11 +1925,8 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
||||||
}
|
}
|
||||||
if (res == overlapped_unknown)
|
if (res == overlapped_unknown)
|
||||||
{
|
{
|
||||||
HANDLE w4[3] = { get_overlapped ()->hEvent, signal_arrived,
|
|
||||||
pthread::get_cancel_event () };
|
|
||||||
DWORD n = w4[2] ? 3 : 2;
|
|
||||||
HANDLE h = writing ? get_output_handle () : get_handle ();
|
HANDLE h = writing ? get_output_handle () : get_handle ();
|
||||||
DWORD wfres = WaitForMultipleObjects (n, w4, false, INFINITE);
|
DWORD wfres = cygWFMO (1, INFINITE, get_overlapped ()->hEvent);
|
||||||
/* Cancelling here to prevent races. It's possible that the I/O has
|
/* Cancelling here to prevent races. It's possible that the I/O has
|
||||||
completed already, in which case this is a no-op. Otherwise,
|
completed already, in which case this is a no-op. Otherwise,
|
||||||
WFMO returned because 1) This is a non-blocking call, 2) a signal
|
WFMO returned because 1) This is a non-blocking call, 2) a signal
|
||||||
|
@ -1960,7 +1957,7 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte
|
||||||
pthread::static_cancel_self (); /* never returns */
|
pthread::static_cancel_self (); /* never returns */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug_printf ("GetOverLappedResult failed, h %p, bytes %u, w4: %p, %p, %p %E", h, *bytes, w4[0], w4[1], w4[2]);
|
debug_printf ("GetOverLappedResult failed, h %p, bytes %u, %E", h, *bytes);
|
||||||
res = overlapped_error;
|
res = overlapped_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,8 +333,6 @@ fhandler_console::read (void *pv, size_t& buflen)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE w4[3] = { h, signal_arrived, pthread::get_cancel_event () };
|
|
||||||
DWORD nwait = w4[2] ? 3 : 2;
|
|
||||||
DWORD timeout = is_nonblocking () ? 0 : INFINITE;
|
DWORD timeout = is_nonblocking () ? 0 : INFINITE;
|
||||||
char tmp[60];
|
char tmp[60];
|
||||||
|
|
||||||
|
@ -350,7 +348,7 @@ fhandler_console::read (void *pv, size_t& buflen)
|
||||||
|
|
||||||
set_cursor_maybe (); /* to make cursor appear on the screen immediately */
|
set_cursor_maybe (); /* to make cursor appear on the screen immediately */
|
||||||
restart:
|
restart:
|
||||||
switch (WaitForMultipleObjects (nwait, w4, FALSE, timeout))
|
switch (cygWFMO (1, timeout, h))
|
||||||
{
|
{
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -127,6 +127,8 @@ get_inet_addr (const struct sockaddr *in, int inlen,
|
||||||
some greedy Win32 application. Therefore we should never wait
|
some greedy Win32 application. Therefore we should never wait
|
||||||
endlessly without checking for signals and thread cancel event. */
|
endlessly without checking for signals and thread cancel event. */
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
|
/* Using IsEventSignalled like this is racy since another thread could
|
||||||
|
be waiting for signal_arrived. */
|
||||||
if (IsEventSignalled (signal_arrived)
|
if (IsEventSignalled (signal_arrived)
|
||||||
&& !_my_tls.call_signal_handler ())
|
&& !_my_tls.call_signal_handler ())
|
||||||
{
|
{
|
||||||
|
|
|
@ -232,7 +232,6 @@ _sigdelayed:
|
||||||
pushl %eax # siginfo
|
pushl %eax # siginfo
|
||||||
pushl $tls::sig(%ebx) # signal number
|
pushl $tls::sig(%ebx) # signal number
|
||||||
|
|
||||||
call _reset_signal_arrived\@0
|
|
||||||
pushl \$_sigreturn # where to return
|
pushl \$_sigreturn # where to return
|
||||||
pushl $tls::func(%ebx) # user-supplied signal func
|
pushl $tls::func(%ebx) # user-supplied signal func
|
||||||
cmpl \$0,$tls::threadkill(%ebx)#pthread_kill signal?
|
cmpl \$0,$tls::threadkill(%ebx)#pthread_kill signal?
|
||||||
|
|
|
@ -368,8 +368,18 @@ _cygtls::signal_exit (int rc)
|
||||||
{
|
{
|
||||||
extern void stackdump (DWORD, int, bool);
|
extern void stackdump (DWORD, int, bool);
|
||||||
|
|
||||||
|
HANDLE myss = my_sendsig;
|
||||||
my_sendsig = NULL; /* Make no_signals_allowed return true */
|
my_sendsig = NULL; /* Make no_signals_allowed return true */
|
||||||
ForceCloseHandle (my_readsig); /* Stop any currently executing sig_sends */
|
if (&_my_tls == _sig_tls)
|
||||||
|
ForceCloseHandle (my_readsig); /* Stop any currently executing sig_sends */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sigpacket sp = {};
|
||||||
|
sp.si.si_signo = __SIGEXIT;
|
||||||
|
DWORD len;
|
||||||
|
WriteFile (myss, &sp, sizeof (sp), &len, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
SetEvent (signal_arrived); /* Avoid potential deadlock with proc_lock */
|
SetEvent (signal_arrived); /* Avoid potential deadlock with proc_lock */
|
||||||
|
|
||||||
if (rc == SIGQUIT || rc == SIGABRT)
|
if (rc == SIGQUIT || rc == SIGABRT)
|
||||||
|
@ -493,7 +503,7 @@ create_signal_arrived ()
|
||||||
return;
|
return;
|
||||||
/* local event signaled when main thread has been dispatched
|
/* local event signaled when main thread has been dispatched
|
||||||
to a signal handler function. */
|
to a signal handler function. */
|
||||||
signal_arrived = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
|
signal_arrived = CreateEvent (&sec_none_nih, false, false, NULL);
|
||||||
ProtectHandle (signal_arrived);
|
ProtectHandle (signal_arrived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,21 @@ struct sigpacket
|
||||||
};
|
};
|
||||||
|
|
||||||
extern HANDLE signal_arrived;
|
extern HANDLE signal_arrived;
|
||||||
|
|
||||||
|
static inline
|
||||||
|
DWORD cygWFMO (DWORD n, DWORD howlong, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start (ap, howlong);
|
||||||
|
HANDLE w4[n + 2];
|
||||||
|
va_start (ap, howlong);
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
w4[i] = va_arg (ap, HANDLE);
|
||||||
|
w4[i++] = signal_arrived;
|
||||||
|
w4[i++] = pthread::get_cancel_event ();
|
||||||
|
return WaitForMultipleObjects (n, w4, FALSE, howlong);
|
||||||
|
}
|
||||||
extern HANDLE sigCONT;
|
extern HANDLE sigCONT;
|
||||||
|
|
||||||
void __stdcall sig_dispatch_pending (bool fast = false);
|
void __stdcall sig_dispatch_pending (bool fast = false);
|
||||||
|
@ -69,7 +84,6 @@ int __stdcall handle_sigprocmask (int sig, const sigset_t *set,
|
||||||
sigset_t *oldset, sigset_t& opmask)
|
sigset_t *oldset, sigset_t& opmask)
|
||||||
__attribute__ ((regparm (3)));
|
__attribute__ ((regparm (3)));
|
||||||
|
|
||||||
extern "C" void __stdcall reset_signal_arrived ();
|
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue