I have a program that only works on Linux, and I have my development environment on Windows.
When I run a WSL command from
cmd
in Windows it works as expected.- When I run
C:wsl echo "foo"
incmd.exe
I getfoo
back via stdout.
- When I run
When I run the same command from within php via
exec
I don’t get any stdout output and get an exit code-1073740791
which I assume is an error.
Cmd.exe:
C:wsl echo "foo" foo
PHP:
<?php $cmd = 'wsl echo "foo"'; exec($cmd, $out, $code); dd($out, $code); ?> // $out is [] // $code is -1073740791
Advertisement
Answer
As discussed in the comments, the underlying issue was that your systemwide Apache web-server service (wampapache64
) was configured to run as NT AuthoritySYSTEM
(aka Local System
or LocalSystem
).
…and running anything like a web-server as LocalSystem
is a very, very bad idea for other reasons, especially when it’s running PHP code – a simple mistake in uploaded-file handling or a failure to correctly sanitize user input could potentially hose your entire computer, especially when it’s a publicly-exposed web-server that a malicious attacker can connect to.
Anyway:
Apparently when a process is running as SYSTEM
it cannot use Win32’s CreateProcess
to invoke wsl
to then indirectly invoke a Linux program.
PHP’s
exec
function is implemented like so:- The
exec
function wraps PHP’s internalVCWD_POPEN
. VCWD_POPEN
is a macro defined as#define VCWD_POPEN(command, type) virtual_popen(command, type)
virtual_popen
varies based on OS:- On Win32,
virtual_popen
simply invokespopen_ex(command, type, CWDG(cwd).cwd, NULL)
.- And
popen_ex
callsCreateProcessAsUserW
orCreateProcessW
to actually start the new process. - I note that
popen_ex
usesOpenThreadToken
to ensure the new process is created with the same user-account and permissions as the parent process – in this caseNT AuthoritySYSTEM
.
- And
- On Win32,
- The
So PHP’s
exec()
is not just a simple wrapper over C’ssystem()
.Whereas if
exec()
was a wrapper oversystem()
then programs would be invoked viacmd.exe
which will behave differently (though that too would likely fail as well)
So by changing your web-server to run as a real user account that meant that the CreateProcess...
call invoked wsl
within a supported environment.