@@ -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,46 +618,49 @@ 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 {
625625 /* If there is anything available in the pipe buffer then signal
626- that. This means that a pipe could still block since you could
627- be trying to write more to the pipe than is available in the
628- buffer but that is the hazard of select().
629-
630- Note that WriteQuotaAvailable is unreliable.
631-
632- Usually WriteQuotaAvailable on the write side reflects the space
633- available in the inbound buffer on the read side. However, if a
634- pipe read is currently pending, WriteQuotaAvailable on the write side
635- is decremented by the number of bytes the read side is requesting.
636- So it's possible (even likely) that WriteQuotaAvailable is 0, even
637- if the inbound buffer on the read side is not full. This can lead to
638- a deadlock situation: The reader is waiting for data, but select
639- on the writer side assumes that no space is available in the read
640- side inbound buffer.
641-
642- Consequentially, there are two possibilities when WriteQuotaAvailable
643- is 0. One is that the buffer is really full. The other is that the
644- reader is currently trying to read the pipe and it is pending.
645- In the latter case, the fact that the reader cannot read the data
646- immediately means that the pipe is empty. In the former case,
647- NtSetInformationFile() in set_pipe_non_blocking(true) will fail
648- with STATUS_PIPE_BUSY, while it succeeds in the latter case.
649- Therefore, we can distinguish these cases by calling set_pipe_non_
650- blocking(true). If it returns success, the pipe is empty, so we
651- return the pipe buffer size. Otherwise, we return 0. */
652- if (fh->get_device () == FH_PIPEW && fpli.WriteQuotaAvailable == 0 )
626+ that. This means that a pipe could still block since you could
627+ be trying to write more to the pipe than is available in the
628+ buffer but that is the hazard of select().
629+
630+ Note that WriteQuotaAvailable is unreliable.
631+
632+ Usually WriteQuotaAvailable on the write side reflects the space
633+ available in the inbound buffer on the read side. However, if a
634+ pipe read is currently pending, WriteQuotaAvailable on the write side
635+ is decremented by the number of bytes the read side is requesting.
636+ So it's possible (even likely) that WriteQuotaAvailable is less than
637+ actual space available in the pipe, even if the inbound buffer is
638+ empty. This can lead to a deadlock situation: The reader is waiting
639+ for data, but select on the writer side assumes that no space is
640+ available in the read side inbound buffer.
641+
642+ Consequentially, there are two possibilities when WriteQuotaAvailable
643+ is less than pipe size. One is that the buffer is really not empty.
644+ The other is that the reader is currently trying to read the pipe
645+ and it is pending.
646+ In the latter case, the fact that the reader cannot read the data
647+ immediately means that the pipe is empty. In the former case,
648+ NtSetInformationFile() in set_pipe_non_blocking(true) will fail
649+ with STATUS_PIPE_BUSY, while it succeeds in the latter case.
650+ Therefore, we can distinguish these cases by calling set_pipe_non_
651+ blocking(true). If it returns success, the pipe is empty, so we
652+ return the pipe buffer size. Otherwise, we return the value of
653+ WriteQuotaAvailable as is. */
654+ if (fh->get_device () == FH_PIPEW
655+ && fpli.WriteQuotaAvailable < fpli.InboundQuota )
653656 {
654657 NTSTATUS status =
655658 ((fhandler_pipe *) fh)->set_pipe_non_blocking (true );
656659 if (status == STATUS_PIPE_BUSY)
657- return 0 ; /* Full */
660+ return fpli. WriteQuotaAvailable ; /* Not empty */
658661 else if (!NT_SUCCESS (status))
659662 /* We cannot know actual write pipe space. */
660- return 1 ;
663+ return PDA_UNKNOWN ;
661664 /* Restore pipe mode to blocking mode */
662665 ((fhandler_pipe *) fh)->set_pipe_non_blocking (false );
663666 /* Empty */
@@ -681,7 +684,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int mode)
681684 return fpli.ReadDataAvailable ;
682685 }
683686 if (fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE)
684- return - 1 ;
687+ return PDA_ERROR ;
685688 return 0 ;
686689}
687690
@@ -731,7 +734,7 @@ peek_pipe (select_record *s, bool from_select)
731734 if (n == 0 && fh->get_echo_handle ())
732735 n = pipe_data_available (s->fd , fh, fh->get_echo_handle (), PDA_READ);
733736
734- if (n < 0 )
737+ if (n == PDA_ERROR )
735738 {
736739 select_printf (" read: %s, n %d" , fh->get_name (), n);
737740 if (s->except_selected )
@@ -772,8 +775,8 @@ peek_pipe (select_record *s, bool from_select)
772775 }
773776 ssize_t n = pipe_data_available (s->fd , fh, h, PDA_WRITE);
774777 select_printf (" write: %s, n %d" , fh->get_name (), n);
775- gotone += s->write_ready = (n > 0 );
776- if (n < 0 && s->except_selected )
778+ gotone += s->write_ready = (n > 0 || n == PDA_UNKNOWN );
779+ if (n == PDA_ERROR && s->except_selected )
777780 gotone += s->except_ready = true ;
778781 }
779782 return gotone;
@@ -986,7 +989,7 @@ peek_fifo (select_record *s, bool from_select)
986989 ssize_t n = pipe_data_available (s->fd , fh, fh->get_handle (), PDA_WRITE);
987990 select_printf (" write: %s, n %d" , fh->get_name (), n);
988991 gotone += s->write_ready = (n > 0 );
989- if (n < 0 && s->except_selected )
992+ if (n == PDA_ERROR && s->except_selected )
990993 gotone += s->except_ready = true ;
991994 }
992995 return gotone;
@@ -1412,7 +1415,7 @@ peek_pty_slave (select_record *s, bool from_select)
14121415 ssize_t n = pipe_data_available (s->fd , fh, h, PDA_WRITE);
14131416 select_printf (" write: %s, n %d" , fh->get_name (), n);
14141417 gotone += s->write_ready = (n > 0 );
1415- if (n < 0 && s->except_selected )
1418+ if (n == PDA_ERROR && s->except_selected )
14161419 gotone += s->except_ready = true ;
14171420 }
14181421 return gotone;
0 commit comments