[PATCH/RFC] console: avoid master-thread suspend request from non-master processes

飛飛飛 <[email protected]>
Newsgroups gmane.os.cygwin.patches
Message-ID <CAD8hRBMi6qaH8xP4Zw0j0VpTz0CFLRRU2cb--H4FCZcpQ=nhEA@mail.gmail.com>
Hi,
I have been investigating a reproducible hang in highly parallel builds on
Windows 11, especially while building LibreOffice with multiple jobs.
The hang appears to involve fhandler_console::close() calling:

set_disable_master_thread (true, this);


even from processes that do not have a local console master thread.

set_disable_master_thread() updates the shared disable_master_thread state
and then waits for:

while (con.master_thread_suspended != x)
  Sleep (1);

During testing I captured a case where one process published a suspend
request (true) and started waiting for

 master_thread_suspended == true,

but another process later published false into the same shared state before
the first request had completed.

The first process was then left waiting indefinitely.
In the captured trace, both requesting processes had:

master_thread_started = 0

while the actual console owner/master-thread process was a different
process.
A minimal guard in
 fhandler_console::close() avoids this:

if (master_thread_started)
  set_disable_master_thread (true, this);

This prevents processes without a local master thread from entering the
master-thread suspend request/wait path.
The intent is not to change Windows process/thread scheduling. It only
restricts Cygwin's shared console master-thread control to a process which
actually has a local master thread.
This also avoids non-master processes entering a wait loop whose completion
condition may be invalidated by another process modifying the same shared
state.
Test results:

Windows 11
AMD Ryzen 7 9800X3D
Intel i7-13620
parallel LibreOffice builds

repeated high-parallelism testing
full LibreOffice build completed successfully with the guard applied
Without the guard, I was able to reproduce the hang and capture the request
overwrite described above.
With the guard restored, the full LibreOffice build completed successfully
with exit code 0.

One possible trade-off is that processes without a local master thread can
no longer request suspension of the console master thread through this
path. So this narrows some existing cross-process master-thread control
behavior.

So far I have not observed a functional regression from this restriction on
the tested Windows 11 systems.
My current understanding is that the important behavioral change is very
small: processes without master_thread_started no longer enter the
potentially unbounded set_disable_master_thread() wait path.
I would appreciate feedback on whether this ownership restriction is
consistent with the intended console master-thread design.
Thanks.




🫆Trace Process Log🫆

Process A:
  started=0
  publish disable=1
  wait for suspended=1

Process B:
  started=0
  publish disable=0
  completes immediately

Process A:
  never completes
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.