Re: [PATCH v7] Cygwin: pty: Fix race issue between starting and exiting non-cygwin apps

Mark Geisert <[email protected]> Wed, 24 Jun 2026 00:09:26 -0700
Newsgroups gmane.os.cygwin.patches
Message-ID <[email protected]>
Hi Takashi,

This v7 LGTM.  OK to push.
Thanks,

..mark

On 6/23/2026 3:51 PM, Takashi Yano wrote:
> Without this patch, when a non-cygwin program (A) is about to exit, and
> another non-cygwin program (B) is started, input transferring between
> cyg-pipe and nat-pipe may not work as expected. When the non-cygwin
> program (A) exits, input transferring from nat-pipe to cyg-pipe will be
> performed. However, the the non-cygwin program (B) will performs input
> transferring from cyg-pipe to nat-pipe at the same time. The mechanism
> of the problem is as follows.
>   1) The the non-cygwin program (A) checks current input pipe state,
>      then it is nat-pipe since the this program is a non-cygwin program.
>      The program (A) also checks if any handover target exists, but
>      it is not found since the program (B) is not started yet. So,
>      the program (A) decided to transfer input form nat-pipe to cyg-
>      pipe.
>   2) Before the non-cygwin (A) program performs input transferring,
>      if the non-cygwin program (B) is started and checks the input
>      pipe state, it is nat-pipe state, so the non-cygwin program (B)
>      does not perform input transferring.
>   3) However, just after that, the non-cygwin program (A) performs
>      input transferring from nat-pipe to cyg-pipe, so typeahead input
>      will be stored in cyg-pipe.
>   4) The non-cygwin program (B) cannot read the typeahead input
>      because it is now in the cyg-pipe.
> 
> The following code demonstrates the issue.
>    #include <stdio.h>
>    #include <stdlib.h>
>    #include <unistd.h>
> 
>    int main(int argc, char *argv[])
>    {
>      int n = 1;
>      if (argc > 1)
>        n = atoi(argv[1]);
>      if (fork()) {
>        execlp("cmd.exe", "cmd", NULL);
>        perror("execlp(\"cmd\"): ");
>      }
>      for (int i=0; i<n; i++) {
>        if (fork() == 0) {
>          execlp("./winsleep.exe", "winsleep", "0", NULL);
>          perror("execlp(\"winsleep\"): ");
>        }
>      }
>      return 0;
>    }
> 
> Transferring input itself is guarded by input_mutex, but the pre-
> check is not. With this patch, the guard is enhanced so that the
> state check and transferring input are done in atomic way.
> 
> Fixes: f20641789427 ("Cygwin: pty: Reduce unecessary input transfer.")
> Signed-off-by: Takashi Yano <[email protected]>
> Reviewed-by: Mark Geisert <[email protected]>
> ---
>   winsup/cygwin/fhandler/pty.cc           | 99 +++++++++++++++----------
>   winsup/cygwin/local_includes/fhandler.h |  2 +
>   2 files changed, 60 insertions(+), 41 deletions(-)
[...]