* 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:
		| @@ -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> | ||||
|  | ||||
| 	* 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; | ||||
|     } | ||||
|  | ||||
|   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); | ||||
|  | ||||
|   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 + 1: | ||||
|       reset_signal_arrived (); | ||||
|       myself->stopsig = SIGCONT; | ||||
|       myself->alert_parent (SIGCONT); | ||||
|       break; | ||||
| @@ -1325,25 +1324,42 @@ events_terminate () | ||||
| int | ||||
| _cygtls::call_signal_handler () | ||||
| { | ||||
|   int this_sa_flags = 0; | ||||
|   /* Call signal handler.  */ | ||||
|   while (sig && func) | ||||
|   int this_sa_flags = SA_RESTART; | ||||
|   while (1) | ||||
|     { | ||||
|       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; | ||||
|       int thissig = sig; | ||||
|       void (*thisfunc) (int) = func; | ||||
|  | ||||
|       pop (); | ||||
|       reset_signal_arrived (); | ||||
|       sigset_t this_oldmask = set_process_mask_delta (); | ||||
|       int this_errno = saved_errno; | ||||
|       sig = 0; | ||||
|       unlock ();	// make sure synchronized | ||||
|       incyg = 0; | ||||
|       if (!(this_sa_flags & SA_SIGINFO)) | ||||
| 	{ | ||||
| 	  void (*sigfunc) (int) = thisfunc; | ||||
| 	  incyg = false; | ||||
| 	  sigfunc (thissig); | ||||
| 	} | ||||
|       else | ||||
| @@ -1351,27 +1367,19 @@ _cygtls::call_signal_handler () | ||||
| 	  siginfo_t thissi = infodata; | ||||
| 	  void (*sigact) (int, siginfo_t *, void *) = (void (*) (int, siginfo_t *, void *)) thisfunc; | ||||
| 	  /* no ucontext_t information provided yet */ | ||||
| 	  incyg = false; | ||||
| 	  sigact (thissig, &thissi, NULL); | ||||
| 	} | ||||
|       incyg = 1; | ||||
|       incyg = true; | ||||
|       set_signal_mask (this_oldmask, _my_tls.sigmask); | ||||
|       if (this_errno >= 0) | ||||
| 	set_errno (this_errno); | ||||
|     } | ||||
|  | ||||
|   unlock (); | ||||
|   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 | ||||
| _cygtls::copy_context (CONTEXT *c) | ||||
| { | ||||
|   | ||||
| @@ -1925,11 +1925,8 @@ fhandler_base_overlapped::wait_overlapped (bool inres, bool writing, DWORD *byte | ||||
|     } | ||||
|   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 (); | ||||
|       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 | ||||
| 	 completed already, in which case this is a no-op.  Otherwise, | ||||
| 	 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 */ | ||||
|       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; | ||||
| 	} | ||||
|     } | ||||
|   | ||||
| @@ -333,8 +333,6 @@ fhandler_console::read (void *pv, size_t& buflen) | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   HANDLE w4[3] = { h, signal_arrived, pthread::get_cancel_event () }; | ||||
|   DWORD nwait = w4[2] ? 3 : 2; | ||||
|   DWORD timeout = is_nonblocking () ? 0 : INFINITE; | ||||
|   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 */ | ||||
| restart: | ||||
|       switch (WaitForMultipleObjects (nwait, w4, FALSE, timeout)) | ||||
|       switch (cygWFMO (1, timeout, h)) | ||||
| 	{ | ||||
| 	case WAIT_OBJECT_0: | ||||
| 	  break; | ||||
|   | ||||
| @@ -127,6 +127,8 @@ get_inet_addr (const struct sockaddr *in, int inlen, | ||||
| 	     some greedy Win32 application.  Therefore we should never wait | ||||
| 	     endlessly without checking for signals and thread cancel event. */ | ||||
| 	  pthread_testcancel (); | ||||
| 	  /* Using IsEventSignalled like this is racy since another thread could | ||||
| 	     be waiting for signal_arrived. */ | ||||
| 	  if (IsEventSignalled (signal_arrived) | ||||
| 	      && !_my_tls.call_signal_handler ()) | ||||
| 	    { | ||||
|   | ||||
| @@ -232,7 +232,6 @@ _sigdelayed: | ||||
| 	pushl	%eax			# siginfo | ||||
| 	pushl	$tls::sig(%ebx)		# signal number | ||||
|  | ||||
| 	call	_reset_signal_arrived\@0 | ||||
| 	pushl	\$_sigreturn		# where to return | ||||
| 	pushl	$tls::func(%ebx)	# user-supplied signal func | ||||
| 	cmpl	\$0,$tls::threadkill(%ebx)#pthread_kill signal? | ||||
|   | ||||
| @@ -368,8 +368,18 @@ _cygtls::signal_exit (int rc) | ||||
| { | ||||
|   extern void stackdump (DWORD, int, bool); | ||||
|  | ||||
|   HANDLE myss = my_sendsig; | ||||
|   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 */ | ||||
|  | ||||
|   if (rc == SIGQUIT || rc == SIGABRT) | ||||
| @@ -493,7 +503,7 @@ create_signal_arrived () | ||||
|     return; | ||||
|   /* local event signaled when main thread has been dispatched | ||||
|      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); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -59,6 +59,21 @@ struct sigpacket | ||||
| }; | ||||
|  | ||||
| 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; | ||||
|  | ||||
| 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) | ||||
|   __attribute__ ((regparm (3))); | ||||
|  | ||||
| extern "C" void __stdcall reset_signal_arrived (); | ||||
| void __stdcall sig_clear (int) __attribute__ ((regparm (1))); | ||||
| void __stdcall sig_set_pending (int) __attribute__ ((regparm (1))); | ||||
| int __stdcall handle_sigsuspend (sigset_t); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user