I always find it a bit unfair when I see sloppy C programs used
for shock value. What if the Rust developer uses fork().unwrap_or(default_value) in a hurry,
or writes<p><pre><code> if let Some(child) = fork() {
do_only_child_stuff();
} else {
do_only_parent_stuff();
}
</code></pre>
or<p><pre><code> if let Some(ForkResult::Child) = fork() {
do_only_child_stuff();
} else {
do_only_parent_stuff();
}
</code></pre>
Now, if you're about to tell me that the examples above are totally stupid and no
developer would do such a thing, then you know how I feel about the sloppy
C versions. Doing a system call and not checking for error is totally
stupid as well.<p>By the way, you can also write your own wrapper functions in C,
that transform the return value into something like<p><pre><code> struct fork_status {
enum { ERROR, PARENT, CHILD } state;
int ret;
};
</code></pre>
Then Clang and GCC will warn you about missing switch cases.<p>That said, the libc bindings in Rust are pretty low-level and a project that
offers higher-level wrappers can be very helpful, so I hope my comment doesn't
create the impression that I'm ripping on the project itself.
I was very confused. I thought this had something to do with Rust and nix[1].<p>[1]: <a href="https://nixos.org/nix/" rel="nofollow">https://nixos.org/nix/</a>
I maintain LuaJIT syscall bindings <a href="https://github.com/justincormack/ljsyscall" rel="nofollow">https://github.com/justincormack/ljsyscall</a> - they cover quite a lot, namespaces, netlink and so on. I spent quite a bit of time making them more intuitive than the raw bindings, with consistent error handling, also namespacing constants and so on. It is definitely useful to have these types of interfaces not in C.
Minor nit pick but don't you typically do something like this in C<p>pid_t childPid;<p>switch (childPid = fork()) {<p>case -1:
... /<i>error handling </i>/;<p>case 0:
... /<i>Child Specific</i>/<p>default:
sleep (5);
}<p>edit - seems to mangle formatting but something like that seems fairly clean.
I can't help but think they're trying to fix something that isn't broken at all.<p>Adding new abstraction layers rarely helps when doing systems programming. You (as in "the developer") want to be as near to the machine as possible. C does this pretty well.<p>Perhaps I'm just getting old :-(
This gets me thinking how awesome it would be to have functional programming on *nix systems, like Haskell (specifically). At least then it might be forcibly designed to be made more useful and ultimately get more people on board. One can dream.
In reliability theory "X failed" is a poor error message. What we want to know is which failure mode has been triggered.<p>The function of kill is to kill a given pid, so there are two failure modes : "the pid didn't exist" or "the pid didn't die"
The term NIX is becoming a bit overloaded - we've got the Nix package manger which run on NixOS, Nix the Rust library all of which can run on most 'Nix systems.
We have switched to Nix as internal dependency manager for our C++ project. It is really exciting! No more "after commit XXX you need to (re)build/update YYY with ZZZ". Developers just type `nix-shell` and get sane guaranted to work environment on their local machines corresponding to git HEAD. If we need to add or patch dependency we just edit and commit nix file. And if developer need to rollback to old commit/branch it will get old/custom environment from cache without submodule rebuilds.
<i>"the return value is conveying three different things all at once. [...] That’s a lot of information for one poor little pid_t—usually a 32-bit integer—to convey!"</i><p>Someone never had to bit-pack their programs to save memory, disk space, or bandwidth. In fact, it's a huge waste of memory; if you only need 3 bits, a 'char' would have sufficed. Saves 24 bits!<p>Of course, we could use nibbles to make data structures where the fork return value only takes up 3 bits instead of a whole byte, but that could be considered micro-optimizing. (the compiler may do this for us anyway, though)