A bad NIF crashes the entire VM and breaks the Erlang/Elixir model of failure handling, so you really should not put code that crashes in there.
If you read his 2003[1] thesis, at page 36 he quotes a paper from Jim Gray (who worked at Tandem computers and was a Turing award winner)
Although compiler checking and exception handling provided by programming languages are real assets, history seems to have favored the run-time checks plus the process approach to fault-containment. It has the virtue of simplicity—if a process or its processor misbehaves, stop it
and the on page 37 The idea of “fail-fast” modules is mirrored in our guidelines for programming where we say that processes should only do when they are supposed to do according to the specification, otherwise they should crash.
and then on page 40 Error handling is non-local.
When we make a fault-tolerant system we need at least two physically separated computers. Using a single computer will not work, if it crashes, all is lost. The simplest fault-tolerant system we can imagine has exactly two computers, if one computer crashes, then the other computer should take over what the first computer was doing. In this simple situation even the software for fault-recovery must be non-local; the error occurs on the first machine, but is corrected by software running on the second machine.
So actually the VM crash is a signal: something's gone really bad, don't even try to recover, just let it die and let some other non-local process take over (the OS, some `forever` like script, a process on another machine...).Do they fail the entire VM, too?
As a operator/user, you can certainly write some code to scan for large processes, and kill them; with a fair bit of success, but that's not a great thing for the toolkit to do, it doesn't have a good way to tell what's too big or what's intended.
[1] See max_heap_size under http://erlang.org/documentation/doc-9.0/erts-9.0/doc/html/er...
For example: what happens if I run this code?
public class Main {
public static void main(String[] args) {
Object[] o = null;
while (true) {
o = new Object[] {o};
}
}
}
What happens if there is a bug in some JNI code that cause a segfault?What Erlang programming style tries to teach is not to avoid crashes by being very defensive and trying to prevent every possible error condition (it's impossible), but to detect them by being fault tolerant and restart the process from a good state.
A NIF is basically VM code that undergo some minor limitation and runs at full speed.
BEAM is not a sandbox and will (probably) never be.
The most important lesson Erlang teaches is that there could be no recovery from crashes from the same code that crashed.
That's why in OTP Supervisors are in the shape of a tree, each level is responsible for its children and only its children.
If you need control on some process tree, you start another supervisor to supervise it and so on.
The same goes for the VM: if you need to supervise the VM, you start an external process to check its status.
A crashed process is better than a process that misbehaves.
Non locality of error handling is the only way to be really fault tolerant.