cygrunsrv + sshd + rsync = 20 times too slow -- throttled?
Corinna Vinschen
corinna-cygwin@cygwin.com
Thu Sep 16 13:25:46 GMT 2021
On Sep 16 22:02, Takashi Yano wrote:
> On Thu, 16 Sep 2021 18:09:05 +0900
> Takashi Yano wrote:
> > I encountered a problem with current git head.
> >
> > To reproduce the problem:
> > 1) Make the CPU hight load state (100% load for all cores).
> > 2) Run '/bin/echo AAAAAAAAAAA 2>&1 |cat' several times.
> > Sometimes, no output is shown.
> >
> > This seems to be a race issue between multiple pipe writers.
> > Now I am investigating the problem.
>
> I would like to propose three additional patches, two are for
> the issue above (0001 and 0003), and the other one (0002) fixes
> the error handling.
>
> Please have a look at patches attached.
> diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc
> index fd2ab87af..7eedc010c 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,10 @@ fhandler_pipe_fifo::reader_closed ()
> {
> if (!query_hdl)
> return false;
> + cygwait (hdl_cnt_mtx);
This is missing an `if (hdl_cnt_mtx)' check.
Also, given you're using hdl_cnt_mtx only for short-lived blocking,
you may want to reduce the overhead and just call WFSO with INFINITE
timeout.
> int n_reader = get_obj_handle_count (query_hdl);
> int n_writer = get_obj_handle_count (get_handle ());
> + ReleaseMutex (hdl_cnt_mtx);
> return n_reader == n_writer;
> }
>
> int
> @@ -576,6 +594,7 @@ fhandler_pipe::dup (fhandler_base *child, int flags)
> ftp->set_popen_pid (0);
>
> int res = 0;
> + cygwait (hdl_cnt_mtx);
Same here and all the other cygwait(hdl_cnt_mtx) calls.
It would be great if open_setup() would be converted to a method which
is allowed to fail, rather than ignoring errors in sync object creation
and having to test the handle throughout the code. Given there's only a
single caller of that function (dtable::init_std_file_from_handle), that
shouldn't be much work. But it's certainly better than ignoring creation
failures in the long run.
> + fhs[0]->hdl_cnt_mtx = CreateMutexW (sa, FALSE, NULL);
> + if (!fhs[0]->hdl_cnt_mtx)
> + {
> + CloseHandle (fhs[0]->read_mtx);
> + CloseHandle (fhs[0]->select_sem);
> + delete fhs[0];
> + NtClose (r);
> + CloseHandle (fhs[1]->select_sem);
> + CloseHandle (fhs[1]->query_hdl);
> + delete fhs[1];
> + NtClose (w);
> + goto out;
> + }
> + if (!DuplicateHandle (GetCurrentProcess (), fhs[0]->hdl_cnt_mtx,
> + GetCurrentProcess (), &fhs[1]->hdl_cnt_mtx,
> + 0, sa->bInheritHandle, DUPLICATE_SAME_ACCESS))
> + {
> + CloseHandle (fhs[0]->read_mtx);
> + CloseHandle (fhs[0]->select_sem);
> + CloseHandle (fhs[0]->hdl_cnt_mtx);
> + delete fhs[0];
> + NtClose (r);
> + CloseHandle (fhs[1]->select_sem);
> + CloseHandle (fhs[1]->query_hdl);
> + delete fhs[1];
> + NtClose (w);
> + goto out;
> + }
> +
> res = 0;
> }
What about converting this to a goto error chain as in
fhandler_pty_slave::setup_pseudoconsole? This makes error handling
much cleaner, IMHO.
Corinna
More information about the Cygwin-developers
mailing list