https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=7f3c22532577ae0a926e8eb8ad63787c9841abbf

commit 7f3c22532577ae0a926e8eb8ad63787c9841abbf
Author:     Corinna Vinschen <[email protected]>
AuthorDate: Sun Aug 18 21:40:51 2024 +0200
Commit:     Corinna Vinschen <[email protected]>
CommitDate: Sun Aug 18 21:40:51 2024 +0200

    Cygwin: pipe: handle signals explicitely in raw_write
    
    The simple cygwait call in fhandler_pipe_fifo::raw_write doesn't
    take the SA_RESTART setting into account. Move handling the
    signal into raw_write.
    
    Fixes: 4b25687ea3ee2 ("Cygwin: fhandler_pipe: add raw_read and raw_write")
    Signed-off-by: Corinna Vinschen <[email protected]>

Diff:
---
 winsup/cygwin/fhandler/pipe.cc | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc
index ae43cbc003da..ce6099d8bc52 100644
--- a/winsup/cygwin/fhandler/pipe.cc
+++ b/winsup/cygwin/fhandler/pipe.cc
@@ -498,9 +498,16 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
                                (PVOID) ptr, len1, NULL, NULL);
          if (status == STATUS_PENDING)
            {
-             while (WAIT_TIMEOUT ==
-                    (waitret = cygwait (evt, (DWORD) 0, cw_cancel | cw_sig)))
+             do
                {
+                 /* To allow constant reader_closed() checking even if the
+                    signal has been set up with SA_RESTART, we're handling
+                    the signal here --> cw_sig_eintr. */
+                 waitret = cygwait (evt, (DWORD) 0, cw_cancel | cw_sig_eintr);
+                 /* Break out if no SA_RESTART. */
+                 if (waitret == WAIT_SIGNALED
+                     && !_my_tls.call_signal_handler ())
+                   break;
                  if (reader_closed ())
                    {
                      CancelIo (get_handle ());
@@ -509,8 +516,10 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
                      goto out;
                    }
                  else
-                   cygwait (select_sem, 10);
+                   cygwait (select_sem, 10, cw_cancel);
                }
+             /* Loop in case of blocking write or SA_RESTART */
+             while (waitret == WAIT_TIMEOUT || waitret == WAIT_SIGNALED);
              /* If io.Status is STATUS_CANCELLED after CancelIo, IO has
                 actually been cancelled and io.Information contains the
                 number of bytes processed so far.

Reply via email to