Cygwin: pipe: Fix race issue regarding handle count.
- This patch fixes the race issue in the handle counting to detect
closure of read pipe, which is introduced by commit f79a4611
.
A mutex hdl_cnt_mtx is introduced for this issue.
This commit is contained in:
parent
d8614e355d
commit
199482654b
|
@ -1176,6 +1176,7 @@ class fhandler_pipe_fifo: public fhandler_base
|
||||||
protected:
|
protected:
|
||||||
size_t pipe_buf_size;
|
size_t pipe_buf_size;
|
||||||
HANDLE query_hdl;
|
HANDLE query_hdl;
|
||||||
|
HANDLE hdl_cnt_mtx;
|
||||||
virtual void release_select_sem (const char *) {};
|
virtual void release_select_sem (const char *) {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -200,7 +200,14 @@ fhandler_pipe::open_setup (int flags)
|
||||||
SECURITY_ATTRIBUTES *sa = sec_none_cloexec (flags);
|
SECURITY_ATTRIBUTES *sa = sec_none_cloexec (flags);
|
||||||
read_mtx = CreateMutex (sa, FALSE, NULL);
|
read_mtx = CreateMutex (sa, FALSE, NULL);
|
||||||
if (!read_mtx)
|
if (!read_mtx)
|
||||||
debug_printf ("CreateMutex failed: %E");
|
debug_printf ("CreateMutex read_mtx failed: %E");
|
||||||
|
}
|
||||||
|
if (!hdl_cnt_mtx)
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES *sa = sec_none_cloexec (flags);
|
||||||
|
hdl_cnt_mtx = CreateMutex (sa, FALSE, NULL);
|
||||||
|
if (!hdl_cnt_mtx)
|
||||||
|
debug_printf ("CreateMutex hdl_cnt_mtx failed: %E");
|
||||||
}
|
}
|
||||||
if (get_dev () == FH_PIPEW && !query_hdl)
|
if (get_dev () == FH_PIPEW && !query_hdl)
|
||||||
set_pipe_non_blocking (is_nonblocking ());
|
set_pipe_non_blocking (is_nonblocking ());
|
||||||
|
@ -390,8 +397,12 @@ fhandler_pipe_fifo::reader_closed ()
|
||||||
{
|
{
|
||||||
if (!query_hdl)
|
if (!query_hdl)
|
||||||
return false;
|
return false;
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
WaitForSingleObject (hdl_cnt_mtx, INFINITE);
|
||||||
int n_reader = get_obj_handle_count (query_hdl);
|
int n_reader = get_obj_handle_count (query_hdl);
|
||||||
int n_writer = get_obj_handle_count (get_handle ());
|
int n_writer = get_obj_handle_count (get_handle ());
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
ReleaseMutex (hdl_cnt_mtx);
|
||||||
return n_reader == n_writer;
|
return n_reader == n_writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -554,11 +565,18 @@ fhandler_pipe::set_close_on_exec (bool val)
|
||||||
set_no_inheritance (select_sem, val);
|
set_no_inheritance (select_sem, val);
|
||||||
if (query_hdl)
|
if (query_hdl)
|
||||||
set_no_inheritance (query_hdl, val);
|
set_no_inheritance (query_hdl, val);
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
set_no_inheritance (hdl_cnt_mtx, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
fhandler_pipe::fixup_after_fork (HANDLE parent)
|
fhandler_pipe::fixup_after_fork (HANDLE parent)
|
||||||
{
|
{
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
{
|
||||||
|
fork_fixup (parent, hdl_cnt_mtx, "hdl_cnt_mtx");
|
||||||
|
WaitForSingleObject (hdl_cnt_mtx, INFINITE);
|
||||||
|
}
|
||||||
if (read_mtx)
|
if (read_mtx)
|
||||||
fork_fixup (parent, read_mtx, "read_mtx");
|
fork_fixup (parent, read_mtx, "read_mtx");
|
||||||
if (select_sem)
|
if (select_sem)
|
||||||
|
@ -567,6 +585,8 @@ fhandler_pipe::fixup_after_fork (HANDLE parent)
|
||||||
fork_fixup (parent, query_hdl, "query_hdl");
|
fork_fixup (parent, query_hdl, "query_hdl");
|
||||||
|
|
||||||
fhandler_base::fixup_after_fork (parent);
|
fhandler_base::fixup_after_fork (parent);
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
ReleaseMutex (hdl_cnt_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -576,6 +596,8 @@ fhandler_pipe::dup (fhandler_base *child, int flags)
|
||||||
ftp->set_popen_pid (0);
|
ftp->set_popen_pid (0);
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
WaitForSingleObject (hdl_cnt_mtx, INFINITE);
|
||||||
if (fhandler_base::dup (child, flags))
|
if (fhandler_base::dup (child, flags))
|
||||||
res = -1;
|
res = -1;
|
||||||
else if (read_mtx &&
|
else if (read_mtx &&
|
||||||
|
@ -589,8 +611,8 @@ fhandler_pipe::dup (fhandler_base *child, int flags)
|
||||||
}
|
}
|
||||||
else if (select_sem &&
|
else if (select_sem &&
|
||||||
!DuplicateHandle (GetCurrentProcess (), select_sem,
|
!DuplicateHandle (GetCurrentProcess (), select_sem,
|
||||||
GetCurrentProcess (), &ftp->select_sem,
|
GetCurrentProcess (), &ftp->select_sem,
|
||||||
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
||||||
{
|
{
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
ftp->close ();
|
ftp->close ();
|
||||||
|
@ -598,13 +620,24 @@ fhandler_pipe::dup (fhandler_base *child, int flags)
|
||||||
}
|
}
|
||||||
else if (query_hdl &&
|
else if (query_hdl &&
|
||||||
!DuplicateHandle (GetCurrentProcess (), query_hdl,
|
!DuplicateHandle (GetCurrentProcess (), query_hdl,
|
||||||
GetCurrentProcess (), &ftp->query_hdl,
|
GetCurrentProcess (), &ftp->query_hdl,
|
||||||
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
||||||
{
|
{
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
ftp->close ();
|
ftp->close ();
|
||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
|
else if (hdl_cnt_mtx &&
|
||||||
|
!DuplicateHandle (GetCurrentProcess (), hdl_cnt_mtx,
|
||||||
|
GetCurrentProcess (), &ftp->hdl_cnt_mtx,
|
||||||
|
0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
__seterrno ();
|
||||||
|
ftp->close ();
|
||||||
|
res = -1;
|
||||||
|
}
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
ReleaseMutex (hdl_cnt_mtx);
|
||||||
|
|
||||||
debug_printf ("res %d", res);
|
debug_printf ("res %d", res);
|
||||||
return res;
|
return res;
|
||||||
|
@ -620,9 +653,17 @@ fhandler_pipe::close ()
|
||||||
}
|
}
|
||||||
if (read_mtx)
|
if (read_mtx)
|
||||||
CloseHandle (read_mtx);
|
CloseHandle (read_mtx);
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
WaitForSingleObject (hdl_cnt_mtx, INFINITE);
|
||||||
if (query_hdl)
|
if (query_hdl)
|
||||||
CloseHandle (query_hdl);
|
CloseHandle (query_hdl);
|
||||||
return fhandler_base::close ();
|
int ret = fhandler_base::close ();
|
||||||
|
if (hdl_cnt_mtx)
|
||||||
|
{
|
||||||
|
ReleaseMutex (hdl_cnt_mtx);
|
||||||
|
CloseHandle (hdl_cnt_mtx);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PIPE_INTRO "\\\\.\\pipe\\cygwin-"
|
#define PIPE_INTRO "\\\\.\\pipe\\cygwin-"
|
||||||
|
@ -834,9 +875,21 @@ fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
|
||||||
FILE_READ_DATA, sa->bInheritHandle, 0))
|
FILE_READ_DATA, sa->bInheritHandle, 0))
|
||||||
goto err_close_select_sem1;
|
goto err_close_select_sem1;
|
||||||
|
|
||||||
|
fhs[0]->hdl_cnt_mtx = CreateMutexW (sa, FALSE, NULL);
|
||||||
|
if (!fhs[0]->hdl_cnt_mtx)
|
||||||
|
goto err_close_query_hdl;
|
||||||
|
if (!DuplicateHandle (GetCurrentProcess (), fhs[0]->hdl_cnt_mtx,
|
||||||
|
GetCurrentProcess (), &fhs[1]->hdl_cnt_mtx,
|
||||||
|
0, sa->bInheritHandle, DUPLICATE_SAME_ACCESS))
|
||||||
|
goto err_close_hdl_cnt_mtx0;
|
||||||
|
|
||||||
res = 0;
|
res = 0;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
err_close_hdl_cnt_mtx0:
|
||||||
|
CloseHandle (fhs[0]->hdl_cnt_mtx);
|
||||||
|
err_close_query_hdl:
|
||||||
|
CloseHandle (fhs[1]->query_hdl);
|
||||||
err_close_select_sem1:
|
err_close_select_sem1:
|
||||||
CloseHandle (fhs[1]->select_sem);
|
CloseHandle (fhs[1]->select_sem);
|
||||||
err_close_select_sem0:
|
err_close_select_sem0:
|
||||||
|
|
Loading…
Reference in New Issue