Last active
July 30, 2024 01:05
-
-
Save oxc/b91f02b55f4973910e5274a26694238d to your computer and use it in GitHub Desktop.
Call execv (works similar for execvp, execve) on Node 20
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ref from "ref-napi"; | |
import ffi from "ffi-napi"; | |
import ref_array_di from "ref-array-di"; | |
const ArrayType = ref_array_di(ref); | |
const StringArray = ArrayType("string"); | |
// from fcntl.h | |
const F_GETFD = 1; /* get close_on_exec */ | |
const F_SETFD = 2; /* set/clear close_on_exec */ | |
const FD_CLOEXEC = 1; /* actually anything with low bit set goes */ | |
export function execv(path: string, args: string[]): number | never { | |
const current = ffi.Library(null, { | |
execv: ["int", ["string", StringArray]], | |
fcntl: ["int", ["int", "int", "int"]], | |
}); | |
function dontCloseOnExit(fd: number) { | |
let flags = current.fcntl(fd, F_GETFD, 0); | |
if (flags < 0) return flags; | |
flags &= ~FD_CLOEXEC; //clear FD_CLOEXEC bit | |
return current.fcntl(fd, F_SETFD, flags); | |
} | |
const argsArray = new StringArray(args.length + 1); | |
for (let i = 0; i < args.length; i++) { | |
argsArray[i] = args[i]; | |
} | |
argsArray[args.length] = null; | |
dontCloseOnExit(process.stdin.fd); | |
dontCloseOnExit(process.stdout.fd); | |
dontCloseOnExit(process.stderr.fd); | |
return current.execv(path, argsArray); | |
} |
This gist was inspired by the existing answers to this StackOverflow question by user1629060 (using ffi) and oleksii-rudenko (removing the "exit on close" flag from the streams).
I have also posted it as an answer here: https://stackoverflow.com/a/77774287/1479482
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
args must contain arg0.
Re-execing the current process might look like: