dscho hooked me up with a workflow to run Git for Windows' test suite on
an msys2-runtime pull request's CI artifacts. With this patch and the
three you pushed (reverting the v2 patch we had applied already, and
applying the two from the cygwin-3_5-branch), the test suite no longer
hangs.


On Mon, 20 Jan 2025, Takashi Yano wrote:

> It seems that current _cygtls::handle_SIGCONT() code sometimes falls
> into a deadlock due to frequent TLS lock/unlock operation in the
> yield() loop. With this patch, the yield() in the wait loop is placed
> outside the TLS lock to avoid frequent TLS lock/unlock.
>
> Fixes: 9ae51bcc51a7 ("Cygwin: signal: Fix another deadlock between main and 
> sig thread")
> Reviewed-by:
> Signed-off-by: Takashi Yano <takashi.y...@nifty.ne.jp>
> ---
>  winsup/cygwin/exceptions.cc           | 36 ++++++++++-----------------
>  winsup/cygwin/local_includes/cygtls.h |  4 +--
>  2 files changed, 15 insertions(+), 25 deletions(-)
>
> diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
> index 4dc4be278..f576c5ff2 100644
> --- a/winsup/cygwin/exceptions.cc
> +++ b/winsup/cygwin/exceptions.cc
> @@ -1420,7 +1420,7 @@ api_fatal_debug ()
>
>  /* Attempt to carefully handle SIGCONT when we are stopped. */
>  void
> -_cygtls::handle_SIGCONT (threadlist_t * &tl_entry)
> +_cygtls::handle_SIGCONT ()
>  {
>    if (NOTSTATE (myself, PID_STOPPED))
>      return;
> @@ -1431,23 +1431,17 @@ _cygtls::handle_SIGCONT (threadlist_t * &tl_entry)
>       Make sure that any pending signal is handled before trying to
>       send a new one.  Then make sure that SIGCONT has been recognized
>       before exiting the loop.  */
> -  bool sigsent = false;
> -  while (1)
> -    if (current_sig) /* Assume that it's ok to just test sig outside of a
> -                        lock since setup_handler does it this way.  */
> -      {
> -     cygheap->unlock_tls (tl_entry);
> -     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
> -      {
> -     current_sig = SIGCONT;
> -     set_signal_arrived (); /* alert sig_handle_tty_stop */
> -     sigsent = true;
> -      }
> +  while (current_sig)  /* Assume that it's ok to just test sig outside of a 
> */
> +    yield ();          /* lock since setup_handler does it this way.  */
> +
> +  lock ();
> +  current_sig = SIGCONT;
> +  set_signal_arrived (); /* alert sig_handle_tty_stop */
> +  unlock ();
> +
> +  while (current_sig == SIGCONT)
> +    yield ();
> +
>    /* Clear pending stop signals */
>    sig_clear (SIGSTOP, false);
>    sig_clear (SIGTSTP, false);
> @@ -1479,11 +1473,7 @@ sigpacket::process ()
>    myself->rusage_self.ru_nsignals++;
>
>    if (si.si_signo == SIGCONT)
> -    {
> -      tl_entry = cygheap->find_tls (_main_tls);
> -      _main_tls->handle_SIGCONT (tl_entry);
> -      cygheap->unlock_tls (tl_entry);
> -    }
> +    _main_tls->handle_SIGCONT ();
>
>    /* SIGKILL is special.  It always goes through.  */
>    if (si.si_signo == SIGKILL)
> diff --git a/winsup/cygwin/local_includes/cygtls.h 
> b/winsup/cygwin/local_includes/cygtls.h
> index 2d490646a..e0de712f4 100644
> --- a/winsup/cygwin/local_includes/cygtls.h
> +++ b/winsup/cygwin/local_includes/cygtls.h
> @@ -194,7 +194,7 @@ public: /* Do NOT remove this public: line, it's a marker 
> for gentls_offsets. */
>    class cygthread *_ctinfo;
>    class san *andreas;
>    waitq wq;
> -  int current_sig;
> +  volatile int current_sig;
>    unsigned incyg;
>    volatile unsigned stacklock;
>    __tlsstack_t *stackptr;
> @@ -274,7 +274,7 @@ public: /* Do NOT remove this public: line, it's a marker 
> for gentls_offsets. */
>    {
>      will_wait_for_signal = false;
>    }
> -  void handle_SIGCONT (threadlist_t * &);
> +  void handle_SIGCONT ();
>    static void cleanup_early(struct _reent *);
>  private:
>    void call2 (DWORD (*) (void *, void *), void *, void *);
>

-- 
Krogt, n. (chemical symbol: Kr):
        The metallic silver coating found on fast-food game cards.
                -- Rich Hall, "Sniglets"

Reply via email to