On Thu, 17 Jul 2025 23:14:21 +0900
Takashi Yano wrote:
> As a starting point, I tried tntroducing locking. It almost works
> as expected, however, sometimes my STC in my first report is hangs
> if N is large e.g. 100. The patch is as attached.
>
> What am I missing?
Patch revised.
--
Takashi Yano <[email protected]>
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index cb58b6eed..100c1246e 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -273,6 +273,7 @@ struct system_call_handle
};
child_info_spawn NO_COPY ch_spawn;
+static NO_COPY SRWLOCK ch_spawn_lock = SRWLOCK_INIT;
extern "C" void __posix_spawn_sem_release (void *sem, int error);
@@ -333,6 +334,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
__try
{
+ AcquireSRWLockExclusive (&ch_spawn_lock);
child_info_types chtype;
if (mode == _P_OVERLAY)
chtype = _CH_EXEC;
@@ -354,13 +356,17 @@ child_info_spawn::worker (const char *prog_arg, const
char *const *argv,
{
set_errno (err);
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
res = newargv.setup (prog_arg, real_path, ext, ac, argv, p_type_exec);
if (res)
- __leave;
+ {
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
+ __leave;
+ }
if (!real_path.iscygexec () && ::cygheap->cwd.get_error ())
{
@@ -369,6 +375,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
::cygheap->cwd.get_error_desc ());
set_errno (::cygheap->cwd.get_error ());
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
@@ -382,6 +389,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
real_path.iscygexec ()))
{
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
@@ -492,6 +500,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
{
set_errno (ENAMETOOLONG);
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
@@ -512,6 +521,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
{
set_errno (E2BIG);
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
set (chtype, real_path.iscygexec ());
@@ -728,6 +738,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
::cygheap->user.reimpersonate ();
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
@@ -781,6 +792,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
if (get_errno () != ENOMEM)
set_errno (EAGAIN);
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
child->dwProcessId = pi.dwProcessId;
@@ -816,6 +828,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
CloseHandle (pi.hProcess);
ForceCloseHandle (pi.hThread);
res = -1;
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
__leave;
}
}
@@ -845,6 +858,10 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
wait for it to exit in maybe_set_exit_code_from_windows(). */
synced = iscygwin () ? sync (pi.dwProcessId, pi.hProcess, INFINITE) :
true;
+ pid_t ch_pid = cygpid;
+ bool ch_iscygwin = iscygwin ();
+ this->cleanup ();
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
switch (mode)
{
case _P_OVERLAY:
@@ -860,7 +877,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
}
else
{
- if (iscygwin ())
+ if (ch_iscygwin)
close_all_files (true);
if (!my_wr_proc_pipe
&& WaitForSingleObject (pi.hProcess, 0) == WAIT_TIMEOUT)
@@ -891,7 +908,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
case _P_WAIT:
case _P_SYSTEM:
system_call.arm ();
- if (waitpid (cygpid, &res, 0) != cygpid)
+ if (waitpid (ch_pid, &res, 0) != ch_pid)
res = -1;
term_spawn_worker.cleanup ();
break;
@@ -901,7 +918,7 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
case _P_NOWAIT:
case _P_NOWAITO:
case _P_VFORK:
- res = cygpid;
+ res = ch_pid;
break;
default:
break;
@@ -909,6 +926,8 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
}
__except (NO_ERROR)
{
+ this->cleanup ();
+ ReleaseSRWLockExclusive (&ch_spawn_lock);
if (get_errno () == ENOMEM)
set_errno (E2BIG);
else
@@ -917,7 +936,6 @@ child_info_spawn::worker (const char *prog_arg, const char
*const *argv,
}
__endtry
term_spawn_worker.close_handle_set ();
- this->cleanup ();
if (envblock)
free (envblock);
--
Problem reports: https://cygwin.com/problems.html
FAQ: https://cygwin.com/faq/
Documentation: https://cygwin.com/docs.html
Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple