Skip to content

Commit

Permalink
Merge pull request #72 from dscho/restore-pipes-blocking-mode
Browse files Browse the repository at this point in the history
Cygwin: pipe: Restore blocking mode of read pipe on close()
  • Loading branch information
dscho committed Sep 18, 2024
2 parents 8d02564 + 8095439 commit 6685316
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
41 changes: 41 additions & 0 deletions winsup/cygwin/fhandler/pipe.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
NTSTATUS status;
IO_STATUS_BLOCK io;
FILE_PIPE_INFORMATION fpi;
bool was_blocking_read_pipe_new = was_blocking_read_pipe;

if (get_device () == FH_PIPER && nonblocking && !was_blocking_read_pipe)
{
status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
FilePipeInformation);
if (NT_SUCCESS (status))
was_blocking_read_pipe_new =
(fpi.CompletionMode == FILE_PIPE_QUEUE_OPERATION);
}

fpi.ReadMode = FILE_PIPE_BYTE_STREAM_MODE;
fpi.CompletionMode = nonblocking ? FILE_PIPE_COMPLETE_OPERATION
Expand All @@ -62,6 +72,11 @@ fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
FilePipeInformation);
if (!NT_SUCCESS (status))
debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status);
else
{
was_blocking_read_pipe = was_blocking_read_pipe_new;
is_blocking_read_pipe = !nonblocking;
}
}

int
Expand Down Expand Up @@ -95,6 +110,8 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode, int64_t uniq_id)
even with FILE_SYNCHRONOUS_IO_NONALERT. */
set_pipe_non_blocking (get_device () == FH_PIPER ?
true : is_nonblocking ());
was_blocking_read_pipe = false;

return 1;
}

Expand Down Expand Up @@ -289,6 +306,9 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
if (!len)
return;

if (is_blocking_read_pipe)
set_pipe_non_blocking (true);

DWORD timeout = is_nonblocking () ? 0 : INFINITE;
DWORD waitret = cygwait (read_mtx, timeout);
switch (waitret)
Expand Down Expand Up @@ -721,6 +741,8 @@ fhandler_pipe::close ()
CloseHandle (query_hdl);
if (query_hdl_close_req_evt)
CloseHandle (query_hdl_close_req_evt);
if (was_blocking_read_pipe)
set_pipe_non_blocking (false);
int ret = fhandler_base::close ();
ReleaseMutex (hdl_cnt_mtx);
CloseHandle (hdl_cnt_mtx);
Expand Down Expand Up @@ -1377,6 +1399,7 @@ fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout,
{
fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
pipe->set_pipe_non_blocking (false);
need_send_noncygchld_sig = true;
}

/* If multiple writers including non-cygwin app exist, the non-cygwin
Expand All @@ -1402,3 +1425,21 @@ fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout,
t->kill_pgrp (__SIGNONCYGCHLD);
}
}

void
fhandler_pipe::sigproc_worker (void)
{
cygheap_fdenum cfd (false);
while (cfd.next () >= 0)
if (cfd->get_dev () == FH_PIPEW)
{
fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
if (pipe->need_close_query_hdl ())
pipe->close_query_handle ();
}
else if (cfd->get_dev () == FH_PIPER)
{
fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
pipe->is_blocking_read_pipe = true;
}
}
3 changes: 3 additions & 0 deletions winsup/cygwin/local_includes/fhandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,8 @@ class fhandler_pipe: public fhandler_pipe_fifo
private:
HANDLE read_mtx;
pid_t popen_pid;
bool was_blocking_read_pipe;
bool is_blocking_read_pipe;
HANDLE query_hdl;
HANDLE hdl_cnt_mtx;
HANDLE query_hdl_proc;
Expand Down Expand Up @@ -1287,6 +1289,7 @@ class fhandler_pipe: public fhandler_pipe_fifo
}
static void spawn_worker (int fileno_stdin, int fileno_stdout,
int fileno_stderr);
static void sigproc_worker (void);
};

#define CYGWIN_FIFO_PIPE_NAME_LEN 47
Expand Down
9 changes: 1 addition & 8 deletions winsup/cygwin/sigproc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1475,14 +1475,7 @@ wait_sig (VOID *)
}
break;
case __SIGNONCYGCHLD:
cygheap_fdenum cfd (false);
while (cfd.next () >= 0)
if (cfd->get_dev () == FH_PIPEW)
{
fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
if (pipe->need_close_query_hdl ())
pipe->close_query_handle ();
}
fhandler_pipe::sigproc_worker ();
break;
}
if (clearwait && !have_execed)
Expand Down

0 comments on commit 6685316

Please sign in to comment.