Skip to content

Commit

Permalink
Avoid sharing the parent process's stdin handle to python on Windows …
Browse files Browse the repository at this point in the history
…+ other Windows bat script fixes (emscripten-core#15146)

* Avoid sharing the parent process's stdin handle to python when invoking python via emcc.bat script, to prevent a rare python deadlock hang.

* Fix Windows .bat scripts from leaking set env. vars.
Work around a Windows 7 batch script exit code issue.
Work around a Windows Python spawn issue: https://bugs.python.org/issue34780

* Do not let anything come between python subprocess spawn and the exit statement (an if() statement would taint the 0 variable)

* Fix bad automerge

* Avoid dispatching emcc from within an if() block in .bat file

* Always use exit in .bat scripts to avoid goto tainting ERRORLEVEL
  • Loading branch information
juj authored Oct 6, 2021
1 parent b6e2934 commit 75b0a5f
Show file tree
Hide file tree
Showing 23 changed files with 988 additions and 6 deletions.
4 changes: 4 additions & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ See docs/process.md for more on how version tagging works.
`__syscall22`) to name-based (e.g. `__syscall_open`). This should not be
a visible change except for folks trying to intercept/implement syscalls
in native code (#15202).
- Fixed launcher batch script issues on Windows, and added two env. vars
EM_WORKAROUND_PYTHON_BUG_34780 and EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG that
can be enabled to work around a Windows Python issue
https://bugs.python.org/issue34780 , and a Windows 7 exit code issue (#15146)

2.0.31 - 10/01/2021
-------------------
Expand Down
51 changes: 49 additions & 2 deletions em++.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,65 @@
:: To make modifications to this file, edit `tools/run_python_compiler.bat` and
:: then run `tools/create_entry_points.py`

:: All env. vars specified in this file are to be local only to this script.
@setlocal

@set EM_PY=%EMSDK_PYTHON%
@if "%EM_PY%"=="" (
set EM_PY=python
)

:: If _EMCC_CCACHE is not set, do a regular invocation of the python compiler driver.
:: Otherwise remove the ccache env. var, and then reinvoke this script with ccache enabled.
@if "%_EMCC_CCACHE%"=="" (
:: Do regular invocation of the python compiler driver
set CMD="%EM_PY%" "%~dp0\%~n0.py"
) else (
:: Remove the ccache env. var, invoke ccache and re-enter this script to take the above branch.
set _EMCC_CCACHE=
set CMD=ccache "%~dp0\%~n0.bat"
)

:: Python Windows bug https://bugs.python.org/issue34780: If this script was invoked via a
:: shared stdin handle from the parent process, and that parent process stdin handle is in
:: a certain state, running python.exe might hang here. To work around this, if
:: EM_WORKAROUND_PYTHON_BUG_34780 is defined, invoke python with '< NUL' stdin to avoid
:: sharing the parent's stdin handle to it, avoiding the hang.

:: On Windows 7, the compiler batch scripts are observed to exit with a non-zero errorlevel,
:: even when the python executable above did succeed and quit with errorlevel 0 above.
:: On Windows 8 and newer, this issue has not been observed. It is possible that this
:: issue is related to the above python bug, but this has not been conclusively confirmed,
:: so using a separate env. var EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG to enable the known
:: workaround this issue, which is to explicitly quit the calling process with the previous
:: errorlevel from the above command.

:: Also must use goto to jump to the command dispatch, since we cannot invoke emcc from
:: inside a if() block, because if a cmdline param would contain a char '(' or ')', that
:: would throw off the parsing of the cmdline arg.
@if "%EM_WORKAROUND_PYTHON_BUG_34780%"=="" (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto NORMAL
) else (
goto NORMAL_EXIT
)
) else (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto MUTE_STDIN
) else (
goto MUTE_STDIN_EXIT
)
)

:NORMAL_EXIT
@%CMD% %*
@exit %ERRORLEVEL%

:MUTE_STDIN
@%CMD% %* < NUL
@exit /b %ERRORLEVEL%

:MUTE_STDIN_EXIT
@%CMD% %* < NUL
@exit %ERRORLEVEL%

:NORMAL
@%CMD% %*
46 changes: 46 additions & 0 deletions em-config.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,56 @@
:: To make modifications to this file, edit `tools/run_python.bat` and then run
:: `tools/create_entry_points.py`

:: All env. vars specified in this file are to be local only to this script.
@setlocal

@set EM_PY=%EMSDK_PYTHON%
@if "%EM_PY%"=="" (
set EM_PY=python
)

:: Python Windows bug https://bugs.python.org/issue34780: If this script was invoked via a
:: shared stdin handle from the parent process, and that parent process stdin handle is in
:: a certain state, running python.exe might hang here. To work around this, if
:: EM_WORKAROUND_PYTHON_BUG_34780 is defined, invoke python with '< NUL' stdin to avoid
:: sharing the parent's stdin handle to it, avoiding the hang.

:: On Windows 7, the compiler batch scripts are observed to exit with a non-zero errorlevel,
:: even when the python executable above did succeed and quit with errorlevel 0 above.
:: On Windows 8 and newer, this issue has not been observed. It is possible that this
:: issue is related to the above python bug, but this has not been conclusively confirmed,
:: so using a separate env. var EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG to enable the known
:: workaround this issue, which is to explicitly quit the calling process with the previous
:: errorlevel from the above command.

:: Also must use goto to jump to the command dispatch, since we cannot invoke emcc from
:: inside a if() block, because if a cmdline param would contain a char '(' or ')', that
:: would throw off the parsing of the cmdline arg.
@if "%EM_WORKAROUND_PYTHON_BUG_34780%"=="" (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto NORMAL
) else (
goto NORMAL_EXIT
)
) else (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto MUTE_STDIN
) else (
goto MUTE_STDIN_EXIT
)
)

:NORMAL_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %*
@exit %ERRORLEVEL%

:MUTE_STDIN
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit /b %ERRORLEVEL%

:MUTE_STDIN_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit %ERRORLEVEL%

:NORMAL
@"%EM_PY%" "%~dp0\%~n0.py" %*
46 changes: 46 additions & 0 deletions emar.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,56 @@
:: To make modifications to this file, edit `tools/run_python.bat` and then run
:: `tools/create_entry_points.py`

:: All env. vars specified in this file are to be local only to this script.
@setlocal

@set EM_PY=%EMSDK_PYTHON%
@if "%EM_PY%"=="" (
set EM_PY=python
)

:: Python Windows bug https://bugs.python.org/issue34780: If this script was invoked via a
:: shared stdin handle from the parent process, and that parent process stdin handle is in
:: a certain state, running python.exe might hang here. To work around this, if
:: EM_WORKAROUND_PYTHON_BUG_34780 is defined, invoke python with '< NUL' stdin to avoid
:: sharing the parent's stdin handle to it, avoiding the hang.

:: On Windows 7, the compiler batch scripts are observed to exit with a non-zero errorlevel,
:: even when the python executable above did succeed and quit with errorlevel 0 above.
:: On Windows 8 and newer, this issue has not been observed. It is possible that this
:: issue is related to the above python bug, but this has not been conclusively confirmed,
:: so using a separate env. var EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG to enable the known
:: workaround this issue, which is to explicitly quit the calling process with the previous
:: errorlevel from the above command.

:: Also must use goto to jump to the command dispatch, since we cannot invoke emcc from
:: inside a if() block, because if a cmdline param would contain a char '(' or ')', that
:: would throw off the parsing of the cmdline arg.
@if "%EM_WORKAROUND_PYTHON_BUG_34780%"=="" (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto NORMAL
) else (
goto NORMAL_EXIT
)
) else (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto MUTE_STDIN
) else (
goto MUTE_STDIN_EXIT
)
)

:NORMAL_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %*
@exit %ERRORLEVEL%

:MUTE_STDIN
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit /b %ERRORLEVEL%

:MUTE_STDIN_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit %ERRORLEVEL%

:NORMAL
@"%EM_PY%" "%~dp0\%~n0.py" %*
46 changes: 46 additions & 0 deletions embuilder.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,56 @@
:: To make modifications to this file, edit `tools/run_python.bat` and then run
:: `tools/create_entry_points.py`

:: All env. vars specified in this file are to be local only to this script.
@setlocal

@set EM_PY=%EMSDK_PYTHON%
@if "%EM_PY%"=="" (
set EM_PY=python
)

:: Python Windows bug https://bugs.python.org/issue34780: If this script was invoked via a
:: shared stdin handle from the parent process, and that parent process stdin handle is in
:: a certain state, running python.exe might hang here. To work around this, if
:: EM_WORKAROUND_PYTHON_BUG_34780 is defined, invoke python with '< NUL' stdin to avoid
:: sharing the parent's stdin handle to it, avoiding the hang.

:: On Windows 7, the compiler batch scripts are observed to exit with a non-zero errorlevel,
:: even when the python executable above did succeed and quit with errorlevel 0 above.
:: On Windows 8 and newer, this issue has not been observed. It is possible that this
:: issue is related to the above python bug, but this has not been conclusively confirmed,
:: so using a separate env. var EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG to enable the known
:: workaround this issue, which is to explicitly quit the calling process with the previous
:: errorlevel from the above command.

:: Also must use goto to jump to the command dispatch, since we cannot invoke emcc from
:: inside a if() block, because if a cmdline param would contain a char '(' or ')', that
:: would throw off the parsing of the cmdline arg.
@if "%EM_WORKAROUND_PYTHON_BUG_34780%"=="" (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto NORMAL
) else (
goto NORMAL_EXIT
)
) else (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto MUTE_STDIN
) else (
goto MUTE_STDIN_EXIT
)
)

:NORMAL_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %*
@exit %ERRORLEVEL%

:MUTE_STDIN
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit /b %ERRORLEVEL%

:MUTE_STDIN_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit %ERRORLEVEL%

:NORMAL
@"%EM_PY%" "%~dp0\%~n0.py" %*
51 changes: 49 additions & 2 deletions emcc.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,65 @@
:: To make modifications to this file, edit `tools/run_python_compiler.bat` and
:: then run `tools/create_entry_points.py`

:: All env. vars specified in this file are to be local only to this script.
@setlocal

@set EM_PY=%EMSDK_PYTHON%
@if "%EM_PY%"=="" (
set EM_PY=python
)

:: If _EMCC_CCACHE is not set, do a regular invocation of the python compiler driver.
:: Otherwise remove the ccache env. var, and then reinvoke this script with ccache enabled.
@if "%_EMCC_CCACHE%"=="" (
:: Do regular invocation of the python compiler driver
set CMD="%EM_PY%" "%~dp0\%~n0.py"
) else (
:: Remove the ccache env. var, invoke ccache and re-enter this script to take the above branch.
set _EMCC_CCACHE=
set CMD=ccache "%~dp0\%~n0.bat"
)

:: Python Windows bug https://bugs.python.org/issue34780: If this script was invoked via a
:: shared stdin handle from the parent process, and that parent process stdin handle is in
:: a certain state, running python.exe might hang here. To work around this, if
:: EM_WORKAROUND_PYTHON_BUG_34780 is defined, invoke python with '< NUL' stdin to avoid
:: sharing the parent's stdin handle to it, avoiding the hang.

:: On Windows 7, the compiler batch scripts are observed to exit with a non-zero errorlevel,
:: even when the python executable above did succeed and quit with errorlevel 0 above.
:: On Windows 8 and newer, this issue has not been observed. It is possible that this
:: issue is related to the above python bug, but this has not been conclusively confirmed,
:: so using a separate env. var EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG to enable the known
:: workaround this issue, which is to explicitly quit the calling process with the previous
:: errorlevel from the above command.

:: Also must use goto to jump to the command dispatch, since we cannot invoke emcc from
:: inside a if() block, because if a cmdline param would contain a char '(' or ')', that
:: would throw off the parsing of the cmdline arg.
@if "%EM_WORKAROUND_PYTHON_BUG_34780%"=="" (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto NORMAL
) else (
goto NORMAL_EXIT
)
) else (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto MUTE_STDIN
) else (
goto MUTE_STDIN_EXIT
)
)

:NORMAL_EXIT
@%CMD% %*
@exit %ERRORLEVEL%

:MUTE_STDIN
@%CMD% %* < NUL
@exit /b %ERRORLEVEL%

:MUTE_STDIN_EXIT
@%CMD% %* < NUL
@exit %ERRORLEVEL%

:NORMAL
@%CMD% %*
46 changes: 46 additions & 0 deletions emcmake.bat
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,56 @@
:: To make modifications to this file, edit `tools/run_python.bat` and then run
:: `tools/create_entry_points.py`

:: All env. vars specified in this file are to be local only to this script.
@setlocal

@set EM_PY=%EMSDK_PYTHON%
@if "%EM_PY%"=="" (
set EM_PY=python
)

:: Python Windows bug https://bugs.python.org/issue34780: If this script was invoked via a
:: shared stdin handle from the parent process, and that parent process stdin handle is in
:: a certain state, running python.exe might hang here. To work around this, if
:: EM_WORKAROUND_PYTHON_BUG_34780 is defined, invoke python with '< NUL' stdin to avoid
:: sharing the parent's stdin handle to it, avoiding the hang.

:: On Windows 7, the compiler batch scripts are observed to exit with a non-zero errorlevel,
:: even when the python executable above did succeed and quit with errorlevel 0 above.
:: On Windows 8 and newer, this issue has not been observed. It is possible that this
:: issue is related to the above python bug, but this has not been conclusively confirmed,
:: so using a separate env. var EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG to enable the known
:: workaround this issue, which is to explicitly quit the calling process with the previous
:: errorlevel from the above command.

:: Also must use goto to jump to the command dispatch, since we cannot invoke emcc from
:: inside a if() block, because if a cmdline param would contain a char '(' or ')', that
:: would throw off the parsing of the cmdline arg.
@if "%EM_WORKAROUND_PYTHON_BUG_34780%"=="" (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto NORMAL
) else (
goto NORMAL_EXIT
)
) else (
@if "%EM_WORKAROUND_WIN7_BAD_ERRORLEVEL_BUG%"=="" (
goto MUTE_STDIN
) else (
goto MUTE_STDIN_EXIT
)
)

:NORMAL_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %*
@exit %ERRORLEVEL%

:MUTE_STDIN
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit /b %ERRORLEVEL%

:MUTE_STDIN_EXIT
@"%EM_PY%" "%~dp0\%~n0.py" %* < NUL
@exit %ERRORLEVEL%

:NORMAL
@"%EM_PY%" "%~dp0\%~n0.py" %*
Loading

0 comments on commit 75b0a5f

Please sign in to comment.