aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2024-10-09 17:34:36 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2024-10-09 17:34:36 +0200
commit8f892e075668c1ed1d668c59d4d0a7929d0c7f5e (patch)
tree2d94e1cc733698eff2e2df7fa5886fcdd9ea720d
parent041848d460f4cce1ba7ef4e61e948fa6499724ca (diff)
Fix issue in previous commit
-rw-r--r--libbutl/process.cxx21
1 files changed, 16 insertions, 5 deletions
diff --git a/libbutl/process.cxx b/libbutl/process.cxx
index 3b21182..f6c1745 100644
--- a/libbutl/process.cxx
+++ b/libbutl/process.cxx
@@ -599,10 +599,10 @@ namespace butl
// Retry to create the child process after the "resource temporarily
// unavailable" (EAGAIN) failure for 1050ms.
//
+ ulock l (process_spawn_mutex);
+
for (size_t i (0);; ++i)
{
- ulock l (process_spawn_mutex); // Note: won't be released in child.
-
// Note that in most non-fork based implementations this call suspends
// the parent thread until the child process calls exec() or
// terminates. This avoids "text file busy" issue (see the fork-based
@@ -618,14 +618,19 @@ namespace butl
? environ
: const_cast<char* const*> (new_env.data ()));
+ l.unlock (); // Release the lock in parent.
+
if (r == 0)
break;
if (i != 15 && r == EAGAIN)
+ {
this_thread::sleep_for (i * 10ms);
+ l.lock ();
+ }
else
fail (r);
- } // Release the lock in parent.
+ }
}
#ifndef LIBBUTL_POSIX_SPAWN_CHDIR
else
@@ -647,10 +652,10 @@ namespace butl
// Retry to create the child process after the "resource temporarily
// unavailable" (EAGAIN) failure for 1050ms.
//
+ ulock l (process_spawn_mutex); // Note: should not be released in child.
+
for (size_t i (0);; ++i)
{
- ulock l (process_spawn_mutex); // Will not be released in child.
-
// Note that the file descriptors with the FD_CLOEXEC flag stay open
// in the child process between fork() and exec() calls. This may
// cause the "text file busy" issue: if some other thread creates a
@@ -662,11 +667,17 @@ namespace butl
//
handle = fork ();
+ if (handle != 0) // Parent.
+ l.unlock ();
+
if (handle != -1)
break;
if (i != 15 && errno == EAGAIN)
+ {
this_thread::sleep_for (i * 10ms);
+ l.lock ();
+ }
else
fail (false /* child */);
} // Release the lock in parent.