summaryrefslogtreecommitdiffstats
path: root/src/engine/SCons/Platform/win32.py
diff options
context:
space:
mode:
authorAdam Gross <grossag@vmware.com>2019-12-06 21:43:52 (GMT)
committerAdam Gross <grossag@vmware.com>2019-12-06 21:45:30 (GMT)
commited66f1338f029a63b7a93f7027f3149ab5376bdd (patch)
treed7f17e6b77d15ed705282bb430e00f982bae6a2b /src/engine/SCons/Platform/win32.py
parentb24e34897212026548d9b5ff0bc20610347f9367 (diff)
downloadSCons-ed66f1338f029a63b7a93f7027f3149ab5376bdd.zip
SCons-ed66f1338f029a63b7a93f7027f3149ab5376bdd.tar.gz
SCons-ed66f1338f029a63b7a93f7027f3149ab5376bdd.tar.bz2
Fix multithreaded Windows builds when a thread has a file open for write
Python 2 enables handle inheritance by default for child processes. It wasn't until Python 3.4 that it was disabled. This causes problems because if a Python action is writing to a file and a child process is spawned at that exact moment, builds fail because of sharing issues.
Diffstat (limited to 'src/engine/SCons/Platform/win32.py')
-rw-r--r--src/engine/SCons/Platform/win32.py59
1 files changed, 34 insertions, 25 deletions
diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py
index 0a3b199..c0cf03b 100644
--- a/src/engine/SCons/Platform/win32.py
+++ b/src/engine/SCons/Platform/win32.py
@@ -51,10 +51,6 @@ try:
import msvcrt
import win32api
import win32con
-
- msvcrt.get_osfhandle
- win32api.SetHandleInformation
- win32con.HANDLE_FLAG_INHERIT
except ImportError:
parallel_msg = \
"you do not seem to have the pywin32 extensions installed;\n" + \
@@ -66,28 +62,41 @@ except AttributeError:
else:
parallel_msg = None
- _builtin_open = open
-
- def _scons_open(*args, **kw):
- fp = _builtin_open(*args, **kw)
- win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
- win32con.HANDLE_FLAG_INHERIT,
- 0)
- return fp
-
- open = _scons_open
-
if sys.version_info.major == 2:
- _builtin_file = file
- class _scons_file(_builtin_file):
- def __init__(self, *args, **kw):
- _builtin_file.__init__(self, *args, **kw)
- win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()),
- win32con.HANDLE_FLAG_INHERIT, 0)
- file = _scons_file
- else:
- # No longer needed for python 3.4 and above. Files are opened non sharable
- pass
+ import __builtin__
+
+ _builtin_file = __builtin__.file
+ _builtin_open = __builtin__.open
+
+ def _scons_fixup_mode(mode):
+ """Adjust 'mode' to mark handle as non-inheritable.
+
+ SCons is multithreaded, so allowing handles to be inherited by
+ children opens us up to races, where (e.g.) processes spawned by
+ the Taskmaster may inherit and retain references to files opened
+ by other threads. This may lead to sharing violations and,
+ ultimately, build failures.
+
+ By including 'N' as part of fopen's 'mode' parameter, all file
+ handles returned from these functions are atomically marked as
+ non-inheritable.
+ """
+ if not mode:
+ # Python's default is 'r'.
+ # https://docs.python.org/2/library/functions.html#open
+ mode = 'rN'
+ elif 'N' not in mode:
+ mode += 'N'
+ return mode
+
+ def _scons_file(name, mode=None, *args, **kwargs):
+ return _builtin_file(name, _scons_fixup_mode(mode), *args, **kwargs)
+
+ def _scons_open(name, mode=None, *args, **kwargs):
+ return _builtin_open(name, _scons_fixup_mode(mode), *args, **kwargs)
+
+ __builtin__.file = _scons_file
+ __builtin__.open = _scons_open