from Hacker News

Rust and Nix = easier Unix systems programming

by kalmar on 4/14/16, 4:46 AM with 81 comments

  • by zuzun on 4/14/16, 8:23 AM

    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

        if let Some(child) = fork() {
            do_only_child_stuff(); 
        } else {
            do_only_parent_stuff();
        }
    
    or

        if let Some(ForkResult::Child) = fork() {
            do_only_child_stuff();
        } else {
            do_only_parent_stuff();
        }
    
    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.

    By the way, you can also write your own wrapper functions in C, that transform the return value into something like

        struct fork_status {
            enum { ERROR, PARENT, CHILD } state;
            int ret;
        };
    
    Then Clang and GCC will warn you about missing switch cases.

    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.

  • by geocar on 4/14/16, 7:18 AM

    I was very confused. I thought this had something to do with Rust and nix[1].

    [1]: https://nixos.org/nix/

  • by subway on 4/14/16, 6:18 AM

    Neat library, way too already-overloaded name.
  • by justincormack on 4/14/16, 12:44 PM

    I maintain LuaJIT syscall bindings https://github.com/justincormack/ljsyscall - 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.
  • by bigger_cheese on 4/14/16, 6:35 AM

    Minor nit pick but don't you typically do something like this in C

    pid_t childPid;

    switch (childPid = fork()) {

    case -1: ... /error handling /;

    case 0: ... /Child Specific/

    default: sleep (5); }

    edit - seems to mangle formatting but something like that seems fairly clean.

  • by sergiolp on 4/14/16, 7:15 AM

    I can't help but think they're trying to fix something that isn't broken at all.

    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.

    Perhaps I'm just getting old :-(

  • by superobserver on 4/14/16, 1:57 PM

    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.
  • by SixSigma on 4/14/16, 6:53 AM

    In reliability theory "X failed" is a poor error message. What we want to know is which failure mode has been triggered.

    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"

  • by bogomipz on 4/15/16, 2:27 AM

    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.
  • by ZephyrP on 4/14/16, 5:06 PM

    I feel there are more promising options for a name than "Nix".
  • by etrain on 4/14/16, 7:00 AM

    type systems are great.
  • by larozin on 4/14/16, 7:35 AM

    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.
  • by peterwwillis on 4/14/16, 3:36 PM

    "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!"

    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!

    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)