Best of luck to xiaq, a fellow fish shell contributor. It's definitely good to see more innovation in the ossified command-line shell space.
Assuming this is planning on using Go's concurrency support, it will be very interesting to see how it deals with the nasty interactions between fork and multithreading.
Thanks ridiculous_fish. I'm still more or less following fish development, and elvish owes a lot to fish.
For now syscall.ForkExec (http://godoc.org/syscall#ForkExec) is sufficient for me. It is written to avoid async-unsafe calls between fork and exec, which is also what fish does IIRC.
The essential function of a shell is to start processes. In Unix and Linux, the usual way to start a new process is to clone yourself (fork), and then have the clone replace itself with a new executable image (exec).
It's kind of roundabout, but the brilliance of this approach lies in what happens between those two calls. There exists process metadata that survives the call to exec, such as where stdout goes, or whether the process is in the foreground. So shells call fork, the clone sets up the metadata for the target process, and then calls exec to start it.
But when a multithreaded program forks, the clone is very limited in what it can do (before exec). In particular, the clone must not acquire a lock that may have been held at the time of fork (which usually rules out heap allocations!). Now say something goes wrong: the clone needs to print an error message, without locking anything. But lots of functions acquire locks internally. How do you know what's safe to call?
fish solves this by providing its own known-safe implementations of printf() and friends, and being careful to only call those after fork. Go solves this by disallowing any user-code between fork and exec. Instead it provides a single posix_spawn-like entry point called ForkExec, and does some black magic (like raw syscalls - see https://code.google.com/p/go/source/browse/src/pkg/syscall/e... ) in between the underlying fork and exec calls.
My hunch is that a shell written in Go will eventually bump up against the limitations of ForkExec. Happily Go has a strong FFI, so you can hopefully implement this stuff in C, if it comes to that!
One of the most frequent things you do in shells is invoking external programs. Unlike in Windows where a CreateProcess does the invocation, in Unix systems this is (traditionally) achieved by a fork/exec combo. See http://en.wikipedia.org/wiki/Fork-exec
Best of luck to xiaq, a fellow fish shell contributor. It's definitely good to see more innovation in the ossified command-line shell space.
Assuming this is planning on using Go's concurrency support, it will be very interesting to see how it deals with the nasty interactions between fork and multithreading.