Skip to content

Conversation

@nagilson
Copy link
Member

@nagilson nagilson commented Jun 13, 2025

What's this

This turns off the 'shell' when running commands for us in vscode. This provides a huge performance boost.
CICD Logs with Spawn:
--info 27.90. 29.21. 26.21. 2.68. (error) 27.
--list-runtimes 30.39. 2.32. (error) 31.

Without Spawn:
--list-runtimes 50. 45. 32 (error).
--info: 46. 41. 32. (error)

Explanation and Context

When spawning a process in node.js, it uses a shell. The shell takes a lot of time. The shell defaults:
Windows Default: process.env.ComSpec or cmd.exe if undefined.
Unix Default: /bin/sh

Here's what doesn't work without a shell:
& (To make a background process)
/* ? Globbing to get wild cards
> << > Redirection
I/O
| Piping - Chain 1 command output to the next.
Shell Environment Variables that aren't set on the system but instead a profile that's launched with the SHELL
"file" escaping.

process.env is used as env by default regardless of shell.

Now, here's a rough list of everything we call:

powershell
dotnet
echo
icacls
reg.exe
id (Unix)
net
set
setx
open
where
which
grep
rm
cat
uname
apt-get and friends

Fun part:
process.spawn makes a system call.
https://github.com/nodejs/node/blob/5fe78006834011621969a76b4f2d98c0e0039b33/deps/uv/src/unix/process.c#L966
https://github.com/nodejs/node/blob/5fe78006834011621969a76b4f2d98c0e0039b33/src/process_wrap.cc#L348C13-L348C21
https://github.com/nodejs/node/blob/5fe78006834011621969a76b4f2d98c0e0039b33/src/env_properties.h#L171

It looks like system calls on Windows resolve the PATH by default without a shell, but they do not on Unix.
Node process uses CreateProcessW and execve.

Windows:
CreateProcessA function (processthreadsapi.h) - Win32 apps | Microsoft Learn
“The directories that are listed in the PATH environment variable [are searched].”
https://github.com/libuv/libuv/blob/b00c5d1a09c094020044e79e19f478a25b8e1431/src/win/process.c#L1067

Unix:
execve(2) - Linux manual page
[Use other] standardised variants of this function provided by libc, including ones that search the PATH environment variable.

@nagilson
Copy link
Member Author

nagilson commented Jun 13, 2025

Ah so only spawn has boolean|string for shell, not exec.... facepalm

nagilson added 6 commits June 13, 2025 15:34
only spawn can use shell = false
spawn uses the direct string. escaping with " " causes it to not find the executable.
need to confirm with weird path names that caused issues before but program files seems to work.

setx "" parsing also no longer functions properly.

noticed that --list-sdks --arch is missing the arch value so fixed that as well
I don't believe we ever use that.
return [];
}

const findSDKsCommand = CommandExecutor.makeCommand(`"${existingPath}"`, ['--list-sdks', '--arch', requestedArchitecture]);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this break Linux/Mac scenarios in the shell? I think we need to look at this from a broader context.

options.shell ??= true;
options.shell ??= os.platform() === 'win32' ? false : true;
// ^ Windows systemcalls (node.js process library uses process_wrap which uses process.cc which makes system calls)
// Windows seems to resolve the PATH by default in a system call. Unix system calls do not.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just respect shell and let the shell do this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant