TSCBasic: change the behaviour of exec
on Windows
#283
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This simultaneously makes
exec
less likeexec
and more likeexec
on POSIX platforms. Replace the use of the ucrt
_execve
in favour ofspelling out the implementation inline with alterations. There are
multiple reasons that this needs to be done.
The concept of
exec
is impossible to map to the process managementstructure on Windows (just as
fork
is). Fundamentally,exec
is areplacement of the process image which will retain the process id and
parts of the libc state (e.g. non-
cloexec
fds in their currentstate). However, the process model on Windows does not have the ability
to do such an operation. Each process is immutable.
_execve
is a wrapper for_spawnl
with_P_OVERLAY
- it simply willcreate a new process and terminate the existing one. This implicitly
breaks the façade - the PID is not inherited -
GetCurrentProcessId()
would return a different value (which would require to be passed from
the parent to the child as the parent state will be demolished and there
is no lineage that is preserved). Additionally, the new process will
only inherit
HANDLE
s which have markedbInheritable
asTRUE
atconstruction time via
CreateFileW
.More importantly, when the
_execve
is used, it firstly inherit theASCII traits which will further limit the use of this already
less-than-useful portability utility. It will limit the file paths even
more than the unicode variant, which is already limited by the Win32
subsystem and requires explicit escape via use of NT style paths to
work around the Win32 path limitations. Secondly, and more user
visible, is the fact that the implementation does not properly hand off
the console. The new process is launched in the background and the
current process is unceremoniously terminated, restoring control to the
command interpreter (cmd.com). The order in which this occurs is
unspecified and uncontrollable (i.e. the new process may start before or
after the termination). More problematically, this results in two
processes with access to the console stdin/stdout/stderr handles, which
now creates a problem of who acquires the input. Most often, this is
manifested as read by the command interpreter rather than the
application, followed by the application rather than the command
interpreter.
We have effectively re-implemented
_execve
in place here, with a fewexceptions:
via an undocumented handoff to ucrt (if for no other reason than we do
not have a good solution to accessing the FD table)
inheritance rules apply to the environment.
CreateProcessW
, which wouldinfluence how the process is created (requires that the program suffix
is a well-known suffix - .exe, .com, etc). Note that this will
prevent the execution of a batch file as that requires that
lpApplicationName
is explicitly set tocmd.exe
and that the firstparameter of the argument string is
/c
rather than the executablepath.
filesystem properly
with a silent breakaway, kill-on-close Job Object to ensure that the
subprocesses of the "exec"-ed image are treated as part of the same
process tree
job object, and then wait for the process termination before the
process exit, preventing the problem of the interrupted execution.
While this has limitations in the precise emulation of
exec
as definedby POSIX, it is sufficient to allow execution of subprocesses as
desired. This has user-visible differences, e.g. PID and file
descriptor states are lost. It has been opined by many others that
fork
andexec
are a mistake, and it may be a better approach toreplace the
exec
call with ainvoke_tool
operation which moreprecisely matches the usecase and retains the behavioural differences
from
exec
.Resolves SR-13806!