Skip to content

Commit 2f6e584

Browse files
tyan0dscho
authored andcommitted
Cygwin: pipe: Make pipe_data_available() return PDA_UNKNOWN
... rather than 1 when the pipe space estimation fails, so that select() and raw_wrie() can perform appropriate fallback handling. In select(), even if pipe space is unknown, return writable to avoid deadlock. Even with select() returns writable, write() can blocked anyway, if data is larger than pipe space. In raw_write(), if the pipe is real non-blocking mode, attempting to write larger data than pipe space is safe. Otherwise, return error. Reviewed-by: Signed-off-by: Takashi Yano <[email protected]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent 034c762 commit 2f6e584

File tree

3 files changed

+16
-12
lines changed

3 files changed

+16
-12
lines changed

winsup/cygwin/fhandler/pipe.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -663,12 +663,13 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
663663
in a very implementation-defined way we can't emulate, but it
664664
resembles it closely enough to get useful results. */
665665
avail = pipe_data_available (-1, this, get_handle (), PDA_WRITE);
666-
if (avail < 1) /* error or pipe closed */
666+
if (avail == PDA_UNKNOWN && real_non_blocking_mode)
667+
avail = len1;
668+
else if (avail == 0 || !PDA_NOERROR (avail))
669+
/* error or pipe closed */
667670
break;
668671
if (avail > len1) /* somebody read from the pipe */
669672
avail = len1;
670-
if (avail == 1) /* 1 byte left or non-Cygwin pipe */
671-
len1 >>= 1;
672673
else if (avail >= PIPE_BUF)
673674
len1 = avail & ~(PIPE_BUF - 1);
674675
else

winsup/cygwin/local_includes/select.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,5 +143,8 @@ ssize_t pipe_data_available (int, fhandler_base *, HANDLE, int);
143143

144144
#define PDA_READ 0x00
145145
#define PDA_WRITE 0x01
146+
#define PDA_ERROR -1
147+
#define PDA_UNKNOWN -2
148+
#define PDA_NOERROR(x) (x >= 0)
146149

147150
#endif /* _SELECT_H_ */

winsup/cygwin/select.cc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode)
601601
if (mode == PDA_READ
602602
&& PeekNamedPipe (h, NULL, 0, NULL, &nbytes_in_pipe, NULL))
603603
return nbytes_in_pipe;
604-
return -1;
604+
return PDA_ERROR;
605605
}
606606

607607
IO_STATUS_BLOCK iosb = {{0}, 0};
@@ -618,7 +618,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode)
618618
access on the write end. */
619619
select_printf ("fd %d, %s, NtQueryInformationFile failed, status %y",
620620
fd, fh->get_name (), status);
621-
return (mode == PDA_WRITE) ? 1 : -1;
621+
return (mode == PDA_WRITE) ? PDA_UNKNOWN : PDA_ERROR;
622622
}
623623
if (mode == PDA_WRITE)
624624
{
@@ -660,7 +660,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode)
660660
return fpli.WriteQuotaAvailable; /* Not empty */
661661
else if (!NT_SUCCESS (status))
662662
/* We cannot know actual write pipe space. */
663-
return 1;
663+
return PDA_UNKNOWN;
664664
/* Restore pipe mode to blocking mode */
665665
((fhandler_pipe *) fh)->set_pipe_non_blocking (false);
666666
/* Empty */
@@ -684,7 +684,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode)
684684
return fpli.ReadDataAvailable;
685685
}
686686
if (fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE)
687-
return -1;
687+
return PDA_ERROR;
688688
return 0;
689689
}
690690

@@ -734,7 +734,7 @@ peek_pipe (select_record *s, bool from_select)
734734
if (n == 0 && fh->get_echo_handle ())
735735
n = pipe_data_available (s->fd, fh, fh->get_echo_handle (), PDA_READ);
736736

737-
if (n < 0)
737+
if (n == PDA_ERROR)
738738
{
739739
select_printf ("read: %s, n %d", fh->get_name (), n);
740740
if (s->except_selected)
@@ -775,8 +775,8 @@ peek_pipe (select_record *s, bool from_select)
775775
}
776776
ssize_t n = pipe_data_available (s->fd, fh, h, PDA_WRITE);
777777
select_printf ("write: %s, n %d", fh->get_name (), n);
778-
gotone += s->write_ready = (n > 0);
779-
if (n < 0 && s->except_selected)
778+
gotone += s->write_ready = (n > 0 || n == PDA_UNKNOWN);
779+
if (n == PDA_ERROR && s->except_selected)
780780
gotone += s->except_ready = true;
781781
}
782782
return gotone;
@@ -989,7 +989,7 @@ peek_fifo (select_record *s, bool from_select)
989989
ssize_t n = pipe_data_available (s->fd, fh, fh->get_handle (), PDA_WRITE);
990990
select_printf ("write: %s, n %d", fh->get_name (), n);
991991
gotone += s->write_ready = (n > 0);
992-
if (n < 0 && s->except_selected)
992+
if (n == PDA_ERROR && s->except_selected)
993993
gotone += s->except_ready = true;
994994
}
995995
return gotone;
@@ -1415,7 +1415,7 @@ peek_pty_slave (select_record *s, bool from_select)
14151415
ssize_t n = pipe_data_available (s->fd, fh, h, PDA_WRITE);
14161416
select_printf ("write: %s, n %d", fh->get_name (), n);
14171417
gotone += s->write_ready = (n > 0);
1418-
if (n < 0 && s->except_selected)
1418+
if (n == PDA_ERROR && s->except_selected)
14191419
gotone += s->except_ready = true;
14201420
}
14211421
return gotone;

0 commit comments

Comments
 (0)