diff options
author | Takashi Yano <takashi.yano@nifty.ne.jp> | 2021-09-16 23:21:57 +0900 |
---|---|---|
committer | Ken Brown <kbrown@cornell.edu> | 2021-09-16 10:57:36 -0400 |
commit | 199482654b07e0603f668caaba8cddb2070cfdb8 (patch) | |
tree | e310233614813f7867eac1ebc2b399b90206b826 | |
parent | d8614e355da550b29fda52c6f59bc7a5e1798b09 (diff) | |
download | newlib-199482654b07e0603f668caaba8cddb2070cfdb8.zip newlib-199482654b07e0603f668caaba8cddb2070cfdb8.tar.gz newlib-199482654b07e0603f668caaba8cddb2070cfdb8.tar.bz2 |
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.
-rw-r--r-- | winsup/cygwin/fhandler.h | 1 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_pipe.cc | 65 |
2 files changed, 60 insertions, 6 deletions
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index eb312cc..31edb18 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1176,6 +1176,7 @@ class fhandler_pipe_fifo: public fhandler_base protected: size_t pipe_buf_size; HANDLE query_hdl; + HANDLE hdl_cnt_mtx; virtual void release_select_sem (const char *) {}; public: diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc index 582b4d5..2068a94 100644 --- a/winsup/cygwin/fhandler_pipe.cc +++ b/winsup/cygwin/fhandler_pipe.cc @@ -200,7 +200,14 @@ fhandler_pipe::open_setup (int flags) SECURITY_ATTRIBUTES *sa = sec_none_cloexec (flags); read_mtx = CreateMutex (sa, FALSE, NULL); 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) set_pipe_non_blocking (is_nonblocking ()); @@ -390,8 +397,12 @@ fhandler_pipe_fifo::reader_closed () { if (!query_hdl) return false; + if (hdl_cnt_mtx) + WaitForSingleObject (hdl_cnt_mtx, INFINITE); int n_reader = get_obj_handle_count (query_hdl); int n_writer = get_obj_handle_count (get_handle ()); + if (hdl_cnt_mtx) + ReleaseMutex (hdl_cnt_mtx); return n_reader == n_writer; } @@ -554,11 +565,18 @@ fhandler_pipe::set_close_on_exec (bool val) set_no_inheritance (select_sem, val); if (query_hdl) set_no_inheritance (query_hdl, val); + if (hdl_cnt_mtx) + set_no_inheritance (hdl_cnt_mtx, val); } void 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) fork_fixup (parent, read_mtx, "read_mtx"); if (select_sem) @@ -567,6 +585,8 @@ fhandler_pipe::fixup_after_fork (HANDLE parent) fork_fixup (parent, query_hdl, "query_hdl"); fhandler_base::fixup_after_fork (parent); + if (hdl_cnt_mtx) + ReleaseMutex (hdl_cnt_mtx); } int @@ -576,6 +596,8 @@ fhandler_pipe::dup (fhandler_base *child, int flags) ftp->set_popen_pid (0); int res = 0; + if (hdl_cnt_mtx) + WaitForSingleObject (hdl_cnt_mtx, INFINITE); if (fhandler_base::dup (child, flags)) res = -1; else if (read_mtx && @@ -589,8 +611,8 @@ fhandler_pipe::dup (fhandler_base *child, int flags) } else if (select_sem && !DuplicateHandle (GetCurrentProcess (), select_sem, - GetCurrentProcess (), &ftp->select_sem, - 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS)) + GetCurrentProcess (), &ftp->select_sem, + 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS)) { __seterrno (); ftp->close (); @@ -598,13 +620,24 @@ fhandler_pipe::dup (fhandler_base *child, int flags) } else if (query_hdl && !DuplicateHandle (GetCurrentProcess (), query_hdl, - GetCurrentProcess (), &ftp->query_hdl, - 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS)) + GetCurrentProcess (), &ftp->query_hdl, + 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS)) + { + __seterrno (); + ftp->close (); + 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); return res; @@ -620,9 +653,17 @@ fhandler_pipe::close () } if (read_mtx) CloseHandle (read_mtx); + if (hdl_cnt_mtx) + WaitForSingleObject (hdl_cnt_mtx, INFINITE); if (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-" @@ -834,9 +875,21 @@ fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode) FILE_READ_DATA, sa->bInheritHandle, 0)) 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; 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: CloseHandle (fhs[1]->select_sem); err_close_select_sem0: |