diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 60c1f594f..03e63dbbe 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -1419,7 +1419,7 @@ api_fatal_debug ()
 
 /* Attempt to carefully handle SIGCONT when we are stopped. */
 void
-_cygtls::handle_SIGCONT ()
+_cygtls::handle_SIGCONT (threadlist_t * &tl_entry)
 {
   if (NOTSTATE (myself, PID_STOPPED))
     return;
@@ -1434,7 +1434,11 @@ _cygtls::handle_SIGCONT ()
   while (1)
     if (sig)		/* Assume that it's ok to just test sig outside of a
 			   lock since setup_handler does it this way.  */
-      yield ();		/* Attempt to schedule another thread.  */
+      {
+	cygheap->unlock_tls (tl_entry); /* Unlock for other threads */
+	yield ();	/* Attempt to schedule another thread.  */
+	tl_entry = cygheap->find_tls (_main_tls);
+      }
     else if (sigsent)
       break;		/* SIGCONT has been recognized by other thread */
     else
@@ -1473,10 +1477,44 @@ sigpacket::process ()
 
   myself->rusage_self.ru_nsignals++;
 
+  /* Wait until another signal is complete. */
+  DWORD t0;
+  t0 = GetTickCount ();
+  tl_entry = cygheap->find_tls (_main_tls);
+  _main_tls->lock ();
+  while (_main_tls->sig)
+    {
+      if (GetTickCount () - t0 < 10)
+	{
+	  _main_tls->unlock ();
+	  cygheap->unlock_tls (tl_entry);
+	  yield();
+	  tl_entry = cygheap->find_tls (_main_tls);
+	  _main_tls->lock ();
+	}
+      else if (!IsEventSignalled (_main_tls->get_signal_arrived ()))
+	{
+	  debug_printf("sig = %d,  "
+		       "but signal_arrived is not raised. Why? Maybe a bug?",
+		       _main_tls->sig);
+	  _main_tls->set_signal_arrived (); /* !! Experimental !! */
+	  t0 = GetTickCount ();
+	}
+      else
+	{
+	  _main_tls->unlock ();
+	  cygheap->unlock_tls (tl_entry);
+	  rc = -1;
+	  goto done;
+	}
+    }
+  _main_tls->unlock ();
+  cygheap->unlock_tls (tl_entry);
+
   if (si.si_signo == SIGCONT)
     {
       tl_entry = cygheap->find_tls (_main_tls);
-      _main_tls->handle_SIGCONT ();
+      _main_tls->handle_SIGCONT (tl_entry);
       cygheap->unlock_tls (tl_entry);
     }
 
diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h
index f67e9136c..062e3defc 100644
--- a/winsup/cygwin/local_includes/cygtls.h
+++ b/winsup/cygwin/local_includes/cygtls.h
@@ -157,6 +157,8 @@ typedef struct struct_waitq
 extern "C" int __sjfault (jmp_buf);
 extern "C" int __ljfault (jmp_buf, int);
 
+struct threadlist_t;
+
 typedef uintptr_t __tlsstack_t;
 
 class _cygtls
@@ -262,7 +264,7 @@ public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */
   {
     will_wait_for_signal = false;
   }
-  void handle_SIGCONT ();
+  void handle_SIGCONT (threadlist_t * &);
   static void cleanup_early(struct _reent *);
 private:
   void call2 (DWORD (*) (void *, void *), void *, void *);
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 9e20ae6f7..2dff06640 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -764,7 +764,7 @@ sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
   if (wait_for_completion)
     {
       sigproc_printf ("Waiting for pack.wakeup %p", pack.wakeup);
-      rc = WaitForSingleObject (pack.wakeup, WSSC);
+      rc = cygwait (pack.wakeup, WSSC);
       ForceCloseHandle (pack.wakeup);
     }
   else
@@ -1329,6 +1329,9 @@ wait_sig (VOID *)
       sigpacket pack = {};
       if (sigq.retry)
 	pack.si.si_signo = __SIGFLUSH;
+      else if ((!PeekNamedPipe (my_readsig, NULL, 0, NULL, &nb, NULL)
+		|| nb == 0) && sigq.start.next)
+	pack.si.si_signo = __SIGFLUSH;
       else if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL))
 	Sleep (INFINITE);	/* Assume were exiting.  Never exit this thread */
       else if (nb != sizeof (pack) || !pack.si.si_signo)
@@ -1468,6 +1471,17 @@ wait_sig (VOID *)
 		      qnext->si.si_signo = 0;
 		    }
 		}
+	      /* Cleanup sigq chain. Remove entries having si_signo == 0.
+		 They were once cleaned obeve, however sigpacket::process()
+		 may set si_signo to 0 using sig_clear(). */
+	      q = &sigq.start;
+	      while ((qnext = q->next))
+		{
+		  if (qnext->si.si_signo)
+		    q = qnext;
+		  else
+		    q->next = qnext->next;
+		}
 	      /* At least one signal still queued?  The event is used in select
 		 only, and only to decide if WFMO should wake up in case a
 		 signalfd is waiting via select/poll for being ready to read a
