From 18bb3df157f0b553f25d13e9e5f230889ebb412f Mon Sep 17 00:00:00 2001 From: Vitaly Cheptsov <4348897+vit9696@users.noreply.github.com> Date: Sat, 2 Sep 2023 22:48:23 +0300 Subject: Fix race condition in MkdirFunc --- CHANGES.txt | 4 ++++ RELEASE.txt | 2 ++ SCons/Node/FS.py | 23 ++++++++++++++++------- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index e323e67..7986818 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -39,6 +39,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Add arm64 to the MSVS supported architectures list for VS2017 and later to be consistent with the current documentation of MSVS_ARCH. + From Vitaly Cheptsov: + - Fix race condition in `Mkdir` which can happen when two `SConscript` + are processed simultaneously by two separate build commands. + From William Deegan: - The --debug flag now has a 'json' option which will write information generated by --debug={count, memory, time, action-timestamps} and about diff --git a/RELEASE.txt b/RELEASE.txt index 8041949..b1e49ff 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -107,6 +107,8 @@ FIXES (Enabled/specified by SCONS_CACHE_MSVC_CONFIG). The existing cache will be discarded if there's a decode error reading it. It's possible there's a race condition creating this issue it in certain CI builds. +- Fixed: race condition in `Mkdir` which can happen when two `SConscript` + are processed simultaneously by two separate build commands. IMPROVEMENTS ------------ diff --git a/SCons/Node/FS.py b/SCons/Node/FS.py index 151a925..3162b21 100644 --- a/SCons/Node/FS.py +++ b/SCons/Node/FS.py @@ -335,13 +335,22 @@ Unlink = SCons.Action.Action(UnlinkFunc, None) def MkdirFunc(target, source, env) -> int: t = target[0] - # This os.path.exists test looks redundant, but it's possible - # when using Install() to install multiple dirs outside the - # source tree to get a case where t.exists() is true but - # the path does already exist, so this prevents spurious - # build failures in that case. See test/Install/multi-dir. - if not t.exists() and not os.path.exists(t.get_abspath()): - t.fs.mkdir(t.get_abspath()) + # - It's possible when using Install() to install multiple + # dirs outside the source tree to get a case where t.exists() + # is false but the path does already exist. + # - It's also possible for multiple SCons processes to try to create + # multiple build directories when processing SConscript files with + # variant dirs. + # Catching OS exceptions and ensuring directory existence prevents + # build failures in these cases. See test/Install/multi-dir. + + if not t.exists(): + abs_path = t.get_abspath() + try: + t.fs.mkdir(abs_path) + except FileExistsError: + pass + return 0 Mkdir = SCons.Action.Action(MkdirFunc, None, presub=None) -- cgit v0.12