A cross-patform way ro spawn processes

Hi,

I’d like to know whether there is a cross-platform way to spawn processes already in the core library or is my only option to call SpawnProcess on Windows and fork+exec on UNIX?

Best regards.

For very basic uses, there’s also libc.system.

Other than that, there’s also a more robust process API in core:os/os2. That’ll eventually replace core:os, but for now it’s work-in-progress.

Thanks. How much is os2 expected to change?

Another question – why might os2.process_exec return a .Not_Exist error?
I’m trying to spawn an ld subprocess from GNU binutils but I’m getting that error. It’s not obvious to me why since when I run which ld in the same way it returns the right location of ld.

Relevant code:

// ...

command: [dynamic]string = { "ld", "-nostdlib", "-o", path_exe }

for path in compiled_libs {
    append(&command, path)
}

_, stdout, stderr := os2.process_exec(os2.Process_Desc{
    command = command[:],
}, context.allocator) or_return

// ...

Spawning as from GNU binutils and piping to it went smooth though.

Just checked and the command succeeds through libc.system.

command_str  := strings.join(command[:], " ")
command_cstr := strings.clone_to_cstring(command_str)

ret := libc.system(command_cstr)
assert(ret == 0) // ok

libc.system will run the command in a shell, which implies PATH lookup as well as all of the other “features” of a shell (e.g. wildcards, variable substitution, etc.). This can be prone to shell injection if you include untrusted input in the command, for instance.

os2.process_exec, at least on Linux, will end up forking and calling execveat, which directly invokes a process by path name. PATH is a feature of the shell, though it seems as execve still checks some default system paths, it won’t check any custom ones defined in the PATH envvar.

Where is your ld executable at? process_exec does seem to find ld on my system, but I have an ld at /bin/ld and /usr/bin/ld–the standard paths.

$ which ld
/nix/store/i53w7x986ifmgzvb8da6zkfms4xzmdrk-gcc-wrapper-13.2.0/bin/ld

$ which as
/nix/store/i53w7x986ifmgzvb8da6zkfms4xzmdrk-gcc-wrapper-13.2.0/bin/as

These are the paths.
What’s curious to me is that as is successfully spawned through process_start but ld isn’t.

Looks like something goes wrong with dup2 in the child process.
I don’t know how reproducible this is but I’m pretty sure it’s a bug is os2.

$ file $(readlink -e $(which ld))
/nix/store/3zaigavb3ig42pb3rmg0cjr85d77aqwz-binutils-wrapper-2.41/bin/ld: a /nix/store/syl4snn859kpqvn9qh91kr7n9i4dws04-bash-5.2p32/bin/bash script, ASCII text executable

$ file $(readlink -e $(which as))
/nix/store/b2lp2479725x61x2wg58x8ajgfz985w0-binutils-2.41/bin/as: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /nix/store/kpy2cyd05vdr6j1h200av81fnlxl
1jw0-glibc-2.39-52/lib/ld-linux-x86-64.so.2, for GNU/Linux 3.10.0, not stripped

ld is a f****** bash script??