Tutorial 5: Dealing With Crashes
Setup
Let’s say you want to create a NIF module from the following example C file test.c:
#include "test.h"
#include "signal.h"
int
works()
{
return 42;
}
void
fails()
{
raise(SIGSEGV);
}The header file test.h looks like this:
extern int works();
extern void fails();We can now create the NIF module as learned in Tutorial 1:
1> nifty:compile("test.h", test, [{port_specs, [{".*","$NIF",["test.c"]}]}]).
generating test.h -> test_nif.c test.erl
==> test (compile)
Compiled src/test_remote.erl
Compiled src/test.erl
Compiling c_src/test_nif.c
okSegfault And Other Crashes
2> test:works().
42
3> test:fails().
Segmentation fault (core dumped)
$Now this is expected, since a segfault crashes the whole system process, but it breaks with the fault-tolerant nature of Erlang. Nifty
allows you to call the created NIF modules without crashing the process. For every NIF module, an additional module with the postfix _remote
is created. This module exports the same functions as the NIF module plus start\0, stop\0 and restart\0. Nifty starts a node in an external
process, which handles the NIF module:
2> test_remote:start().
ok
(p33_p0_master@cola-light)3> test_remote:works().
42
(p33_p0_master@cola-light)4> test_remote:fails().
{error,node_crashed}
(p33_p0_master@cola-light)5> test_remote:stop().
ok
6>As you can see, fails\0 now returns {error, node_crashed} instead of crashing Erlang. After the remote node has crashed, it is necessary to
restart it with restart\0. Otherwise every function call will return {error, node_down}. You can also stop the remote node with stop\0.
Restarting the or stopping is a hard reset of the NIF module. Static C variables and allocated memory will behave as you freshly
loaded the NIF module. This means, that all pointers that you still have are invalid.
| Previous Tutorial | Tutorial Files | Next Tutorial |
|---|