Cygwin: set buffer size for pipes created by non-Cygwin processes

Rename fhandler_pipe_and_fifo::max_atomic_write to pipe_buf_size.
This reflect its actual meaning better.  The fhandler_pipe_and_fifo
constructor initializes it to DEFAULT_PIPEBUFSIZE (== 64K), which is
the buffer size for the windows pipes created by fhandler_pipe and
fhandler_fifo.  But if we inherit a stdio pipe handle from a
non-Cygwin process, the buffer size could be different.

To remedy this, add a method fhandler_pipe::set_pipe_buf_size that
queries the OS for the pipe buffer size, and use it in
dtable::init_std_file_from_handle.
This commit is contained in:
Ken Brown 2021-09-07 17:40:21 -04:00 committed by Corinna Vinschen
parent 27b24069d1
commit 99be238347
3 changed files with 27 additions and 6 deletions

View File

@ -406,6 +406,11 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
} }
if (!fh->init (handle, access, bin)) if (!fh->init (handle, access, bin))
api_fatal ("couldn't initialize fd %d for %s", fd, fh->get_name ()); api_fatal ("couldn't initialize fd %d for %s", fd, fh->get_name ());
if (fh->ispipe ())
{
fhandler_pipe *fhp = (fhandler_pipe *) fh;
fhp->set_pipe_buf_size ();
}
fh->open_setup (openflags); fh->open_setup (openflags);
fh->usecount = 0; fh->usecount = 0;

View File

@ -1172,7 +1172,7 @@ class fhandler_socket_unix : public fhandler_socket
class fhandler_pipe_fifo: public fhandler_base class fhandler_pipe_fifo: public fhandler_base
{ {
protected: protected:
size_t max_atomic_write; size_t pipe_buf_size;
public: public:
fhandler_pipe_fifo (); fhandler_pipe_fifo ();
@ -1192,6 +1192,7 @@ public:
bool ispipe() const { return true; } bool ispipe() const { return true; }
void set_read_mutex (HANDLE mtx) { read_mtx = mtx; } void set_read_mutex (HANDLE mtx) { read_mtx = mtx; }
void set_pipe_buf_size ();
void set_popen_pid (pid_t pid) {popen_pid = pid;} void set_popen_pid (pid_t pid) {popen_pid = pid;}
pid_t get_popen_pid () const {return popen_pid;} pid_t get_popen_pid () const {return popen_pid;}

View File

@ -29,7 +29,7 @@ STATUS_PIPE_EMPTY simply means there's no data to be read. */
|| _s == STATUS_PIPE_EMPTY; }) || _s == STATUS_PIPE_EMPTY; })
fhandler_pipe_fifo::fhandler_pipe_fifo () fhandler_pipe_fifo::fhandler_pipe_fifo ()
: fhandler_base (), max_atomic_write (DEFAULT_PIPEBUFSIZE) : fhandler_base (), pipe_buf_size (DEFAULT_PIPEBUFSIZE)
{ {
} }
@ -269,7 +269,7 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
buffer size - 1. Pending read lowers WriteQuotaAvailable on buffer size - 1. Pending read lowers WriteQuotaAvailable on
the write side and thus affects select's ability to return the write side and thus affects select's ability to return
more or less reliable info whether a write succeeds or not. */ more or less reliable info whether a write succeeds or not. */
ULONG chunk = max_atomic_write - 1; ULONG chunk = pipe_buf_size - 1;
status = NtQueryInformationFile (get_handle (), &io, status = NtQueryInformationFile (get_handle (), &io,
&fpli, sizeof (fpli), &fpli, sizeof (fpli),
FilePipeLocalInformation); FilePipeLocalInformation);
@ -391,12 +391,12 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
if (!len) if (!len)
return 0; return 0;
if (len <= max_atomic_write) if (len <= pipe_buf_size)
chunk = len; chunk = len;
else if (is_nonblocking ()) else if (is_nonblocking ())
chunk = len = max_atomic_write; chunk = len = pipe_buf_size;
else else
chunk = max_atomic_write; chunk = pipe_buf_size;
/* Create a wait event if the pipe or fifo is in blocking mode. */ /* Create a wait event if the pipe or fifo is in blocking mode. */
if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL))) if (!is_nonblocking () && !(evt = CreateEvent (NULL, false, false, NULL)))
@ -894,6 +894,21 @@ nt_create (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE &r, HANDLE &w,
return 0; return 0;
} }
/* Called by dtable::init_std_file_from_handle for stdio handles
inherited from non-Cygwin processes. */
void
fhandler_pipe::set_pipe_buf_size ()
{
NTSTATUS status;
IO_STATUS_BLOCK io;
FILE_PIPE_LOCAL_INFORMATION fpli;
status = NtQueryInformationFile (get_handle (), &io, &fpli, sizeof fpli,
FilePipeLocalInformation);
if (NT_SUCCESS (status))
pipe_buf_size = fpli.InboundQuota;
}
int int
fhandler_pipe::ioctl (unsigned int cmd, void *p) fhandler_pipe::ioctl (unsigned int cmd, void *p)
{ {