mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-08 18:19:08 +08:00
Cygwin: pipe: Restore blocking mode of read pipe on close()/raw_read()
If a cygwin app is executed from a non-cygwin app and the cygwin app exits, the read pipe remains in the non-blocking mode because of the commit fc691d0246b9. Due to this behaviour, the non-cygwin app cannot read the pipe correctly after that. Similarly, if a non-cygwin app is executed from a cygwin app and the non-cygwin app exits, the read pipe remains in the blocking mode. With this patch, the blocking mode of the read pipe is stored into a variable was_blocking_read_pipe on set_pipe_non_blocking() when the cygwin app starts and restored on close(). In addition, the pipe mode is set to non-blocking mode in raw_read() if the mode is blocking mode by referring the variable is_blocking_read_pipe as well. is_blocking_read_pipe is a member of fhandler_pipe class and is set by set_pipe_non_blocking(), so if other process sets the pipe mode to blocking mode, the current process cannot know the pipe is blocking mode. Therefore, is_blocking_read_pipe is also set on the signal __SIGNONCYGCHLD, which is sent to the process group when non-cygwin app is started. Addresses: https://github.com/git-for-windows/git/issues/5115 Fixes: fc691d0246b9 ("Cygwin: pipe: Make sure to set read pipe non-blocking for cygwin apps."); Reported-by: isaacag, Johannes Schindelin <Johannes.Schindelin@gmx.de> Reviewed-by: Corinna Vinschen <corinna@vinschen.de>, Ken Brown <kbrown@cornell.edu> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
This commit is contained in:
parent
784ce7aff8
commit
c7fe29f5cb
@ -54,6 +54,16 @@ fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
|
|||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
FILE_PIPE_INFORMATION fpi;
|
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.ReadMode = FILE_PIPE_BYTE_STREAM_MODE;
|
||||||
fpi.CompletionMode = nonblocking ? FILE_PIPE_COMPLETE_OPERATION
|
fpi.CompletionMode = nonblocking ? FILE_PIPE_COMPLETE_OPERATION
|
||||||
@ -62,6 +72,11 @@ fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
|
|||||||
FilePipeInformation);
|
FilePipeInformation);
|
||||||
if (!NT_SUCCESS (status))
|
if (!NT_SUCCESS (status))
|
||||||
debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status);
|
debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
was_blocking_read_pipe = was_blocking_read_pipe_new;
|
||||||
|
is_blocking_read_pipe = !nonblocking;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -95,6 +110,8 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode, int64_t uniq_id)
|
|||||||
even with FILE_SYNCHRONOUS_IO_NONALERT. */
|
even with FILE_SYNCHRONOUS_IO_NONALERT. */
|
||||||
set_pipe_non_blocking (get_device () == FH_PIPER ?
|
set_pipe_non_blocking (get_device () == FH_PIPER ?
|
||||||
true : is_nonblocking ());
|
true : is_nonblocking ());
|
||||||
|
was_blocking_read_pipe = false;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +306,9 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
|
|||||||
if (!len)
|
if (!len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (is_blocking_read_pipe)
|
||||||
|
set_pipe_non_blocking (true);
|
||||||
|
|
||||||
DWORD timeout = is_nonblocking () ? 0 : INFINITE;
|
DWORD timeout = is_nonblocking () ? 0 : INFINITE;
|
||||||
DWORD waitret = cygwait (read_mtx, timeout);
|
DWORD waitret = cygwait (read_mtx, timeout);
|
||||||
switch (waitret)
|
switch (waitret)
|
||||||
@ -721,6 +741,8 @@ fhandler_pipe::close ()
|
|||||||
CloseHandle (query_hdl);
|
CloseHandle (query_hdl);
|
||||||
if (query_hdl_close_req_evt)
|
if (query_hdl_close_req_evt)
|
||||||
CloseHandle (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 ();
|
int ret = fhandler_base::close ();
|
||||||
ReleaseMutex (hdl_cnt_mtx);
|
ReleaseMutex (hdl_cnt_mtx);
|
||||||
CloseHandle (hdl_cnt_mtx);
|
CloseHandle (hdl_cnt_mtx);
|
||||||
@ -1373,6 +1395,7 @@ fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout,
|
|||||||
{
|
{
|
||||||
fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
|
fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
|
||||||
pipe->set_pipe_non_blocking (false);
|
pipe->set_pipe_non_blocking (false);
|
||||||
|
need_send_noncygchld_sig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If multiple writers including non-cygwin app exist, the non-cygwin
|
/* If multiple writers including non-cygwin app exist, the non-cygwin
|
||||||
@ -1398,3 +1421,21 @@ fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout,
|
|||||||
t->kill_pgrp (__SIGNONCYGCHLD);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1197,6 +1197,8 @@ class fhandler_pipe: public fhandler_pipe_fifo
|
|||||||
private:
|
private:
|
||||||
HANDLE read_mtx;
|
HANDLE read_mtx;
|
||||||
pid_t popen_pid;
|
pid_t popen_pid;
|
||||||
|
bool was_blocking_read_pipe;
|
||||||
|
bool is_blocking_read_pipe;
|
||||||
HANDLE query_hdl;
|
HANDLE query_hdl;
|
||||||
HANDLE hdl_cnt_mtx;
|
HANDLE hdl_cnt_mtx;
|
||||||
HANDLE query_hdl_proc;
|
HANDLE query_hdl_proc;
|
||||||
@ -1287,6 +1289,7 @@ public:
|
|||||||
}
|
}
|
||||||
static void spawn_worker (int fileno_stdin, int fileno_stdout,
|
static void spawn_worker (int fileno_stdin, int fileno_stdout,
|
||||||
int fileno_stderr);
|
int fileno_stderr);
|
||||||
|
static void sigproc_worker (void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CYGWIN_FIFO_PIPE_NAME_LEN 47
|
#define CYGWIN_FIFO_PIPE_NAME_LEN 47
|
||||||
|
@ -1475,14 +1475,7 @@ wait_sig (VOID *)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case __SIGNONCYGCHLD:
|
case __SIGNONCYGCHLD:
|
||||||
cygheap_fdenum cfd (false);
|
fhandler_pipe::sigproc_worker ();
|
||||||
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 ();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (clearwait && !have_execed)
|
if (clearwait && !have_execed)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user