worker: rewrite error handling so os._exit covers all cases
Previously the worker error handling is like:
pid = os.fork() --+
if pid == 0: |
.... | problematic
.... --+
try: --+
.... | worker error handling
--+
If a signal arrives when Python is executing the "problematic" lines, an
external error handling (dispatch.py) will take over the control flow and
it's no longer guaranteed "os._exit" is called (see
86cd09bc13ba for why it
is necessary).
This patch rewrites the error handling so it covers all possible code paths
for a worker even during fork.
Note: "os.getpid() == parentpid" is used to test if the process is parent or
not intentionally, instead of checking "pid", because "pid = os.fork()" may
be not atomic - it's possible that that a signal hits the worker before the
assignment completes [1]. The newly added test replaces "os.fork" to
exercise that extreme case.
[1]: CPython compiles "pid = os.fork()" to 2 byte codes: "CALL_FUNCTION" and
"STORE_FAST", so it's probably not atomic:
def f():
pid = os.fork()
dis.dis(f)
2 0 LOAD_GLOBAL 0 (os)
3 LOAD_ATTR 1 (fork)
6 CALL_FUNCTION 0
9 STORE_FAST 0 (pid)
12 LOAD_CONST 0 (None)
15 RETURN_VALUE
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include guids.wxi ?>
<?include defines.wxi ?>
<Fragment>
<DirectoryRef Id="INSTALLDIR" FileSource="$(var.SourceDir)">
<Component Id="distOutput" Guid="$(var.dist.guid)" Win64='$(var.IsX64)'>
<File Name="python27.dll" KeyPath="yes" />
</Component>
<Directory Id="libdir" Name="lib" FileSource="$(var.SourceDir)/lib">
<Component Id="libOutput" Guid="$(var.lib.guid)" Win64='$(var.IsX64)'>
<File Name="library.zip" KeyPath="yes" />
<File Name="mercurial.base85.pyd" />
<File Name="mercurial.bdiff.pyd" />
<File Name="mercurial.diffhelpers.pyd" />
<File Name="mercurial.mpatch.pyd" />
<File Name="mercurial.osutil.pyd" />
<File Name="mercurial.parsers.pyd" />
<File Name="pyexpat.pyd" />
<File Name="bz2.pyd" />
<File Name="select.pyd" />
<File Name="unicodedata.pyd" />
<File Name="_ctypes.pyd" />
<File Name="_elementtree.pyd" />
<File Name="_hashlib.pyd" />
<File Name="_socket.pyd" />
<File Name="_ssl.pyd" />
</Component>
</Directory>
</DirectoryRef>
</Fragment>
</Wix>