4 ms·
> But despite the apparent strangeness, fork() and exec() are actually pretty convenient once you want to do anything slightly more complicated than just launch
by seiferteric 3y ago
> But despite the apparent strangeness, fork() and exec() are actually pretty convenient once you want to do anything slightly more complicated than just launch a new process.
What I don't understand is why there isn't something for the simple case where we do just want to run another process and not set anything else. There is system() which I believe is just a wrapper for fork/exec, and is tempting to use, but the issue is it just takes a string and passes it to sh which opens you up to shell expansion exploits if you have untrusted/improperly sanitized inputs. I wish there was a version of system() that took an array or args like exec instead and you could specify the command to run directly as well, instead of sh.
- dale_glass 3y agoThat's exactly how it works in Perl. strace -s 80 -f perl -e 'system("ls", "/");' 2>&1 | grep exec ... [pid 1034640] execve("/usr/bin/ls", ["ls", "/"], 0x55b7f79873b0 /* 100 vars */) = 0
- jcranmer 3y agoWhat you're looking for is essentially posix_spawn, if you set the file_actions and attributes parameters to NULL. Then it becomes a function where you specify the executable, arguments, and environment for the new process, with a single error to process.
- thayne 3y agoBut posix_spawn is still implemented with fork/exec (or maybe vfork/exec) and as noted in the blog, has an unnecessarily complicated interface.
- adrian_b 3y agoAs you have yourself said, system() is not a wrapper for fork and exec, but it executes a shell process and it gives to the shell a command to execute, which may be a binary executable or a script. Fork() and exec() are POSIX functions, while system() is a Standard C function that is available in C regardless of the operating system and regardless whether fork() and exec() exist.
- thayne 3y agoOn linux at least, and probably most other unixes, it is implemented with fork/exec. In fact, there are two execs, one to start the shell, and one for the shell to start the actual program. And depending on your command, and the shell implementation you might have another fork as well.
- adrian_b 3y agoHow it is implemented is irrelevant. The Standard C function system() is defined to execute a shell process and its semantics do not depend on how a process is executed by the host operating system. Obviously in any UNIX-derived OS a shell process must be executed via fork and exec, and the shell itself executes children processes also via fork and exec. Under other operating systems no fork or exec are used. What matters is that system() is not defined as a combination of fork with exec, but it does a more complex operation, with a greater overhead, and which works more or less in the same way under any OS. As others have mentioned, POSIX does have a wrapper for fork and exec, which is posix_spawn().
- thayne 3y ago> its semantics do not depend on how a process is executed by the host operating system Implementation details can leak though. For example on unix, if your process uses a lot of memory, a fork can result in an out of memory error, if there isn't enough memory left on the system to copy the parent process memory. And afaict things like how file descriptors are inherited are implementation defined. > which works more or less in the same way under any OS Even ignoring subtle differences in how subprocesses are spawned, there is the little issue that shell escaping and argument splitting works differently on different OSes, or even different shells on the same OS.
- adrian_b 3y agoBecause the differences mentioned by you between shells and OSes are unavoidable, the C standard specifies that the interpretation of the character string passed as an argument of the system() function is implementation-defined and it must be documented by any implementation of the standard C library. This does not change the fact that whether a system() function implementation uses or does not use fork and exec is neither specified by the function definition nor relevant for the user, and in any case system() is not the function that should be used when the intention is to simplify some code that otherwise would invoke fork and exec.