Skip to content

Instantly share code, notes, and snippets.

@davisp
Last active January 21, 2016 05:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davisp/1e71ec7f2f7a70d1b79c to your computer and use it in GitHub Desktop.
Save davisp/1e71ec7f2f7a70d1b79c to your computer and use it in GitHub Desktop.
Test case for NIF segfault with dirty schedulers

niftest

A minimal reproducing test case for a segfault with NIFs and dirty schedulers.

To reproduce:

$ rebar compile eunit

Machine Specifics

Distributor ID: Debian Description: Debian GNU/Linux 8.2 (jessie) Release: 8.2 Codename: jessie

Linux nif-dev 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt11-1+deb8u6 (2015-11-09) x86_64 GNU/Linux

Erlang/OTP 18 [erts-7.2.1] [source] [64-bit] [smp:2:2] [ds:2:2:10] [async-threads:10] [hipe] [kernel-poll:false]

#include <stdio.h>
#include "erl_nif.h"
ErlNifResourceType* obj1_res_type;
ERL_NIF_TERM a_ok;
static int
load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
{
ErlNifSysInfo sys_info;
enif_system_info(&sys_info, sizeof(ErlNifSysInfo));
if(!sys_info.smp_support || !sys_info.dirty_scheduler_support) {
return 1;
}
a_ok = enif_make_atom(env, "ok");
return 0;
}
static ERL_NIF_TERM
nif_fun1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
return a_ok;
}
static ErlNifFunc funcs[] =
{
{"fun1", 0, nif_fun1, ERL_NIF_DIRTY_JOB_IO_BOUND}
};
ERL_NIF_INIT(niftest, funcs, &load, NULL, NULL, NULL);
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7f24fe3fc700 (LWP 8035)]
handle_thr_prgr_later_op (waiting=<optimized out>, aux_work=32,
awdp=0x7f250112af40) at beam/erl_process.c:1920
1920 beam/erl_process.c: No such file or directory.
(gdb) bt
#0 handle_thr_prgr_later_op (waiting=<optimized out>, aux_work=32,
awdp=0x7f250112af40) at beam/erl_process.c:1920
#1 handle_aux_work (waiting=0, orig_aux_work=<optimized out>,
awdp=0x7f250112af40) at beam/erl_process.c:2278
#2 schedule (p=<optimized out>, calls=0) at beam/erl_process.c:9422
#3 0x000000000043db1a in process_main () at beam/beam_emu.c:1254
#4 0x00000000004d3fd5 in sched_dirty_io_thread_func (vesdp=0x7f250112ae40)
at beam/erl_process.c:8149
#5 0x00000000006272a9 in thr_wrapper (vtwd=0x7ffee06ad460)
at pthread/ethread.c:114
#6 0x00007f2502c8d0a4 in start_thread (arg=0x7f24fe3fc700)
at pthread_create.c:309
#7 0x00007f25027ba04d in clone ()
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb) print *awdp
$1 = {sched_id = 0, esdp = 0x0, ssi = 0x0, current_thr_prgr = 1138507,
latest_wakeup = 2, misc = {ix = 0, thr_prgr = 0}, dd = {thr_prgr = 0},
cncld_tmrs = {thr_prgr = 0}, later_op = {thr_prgr = 2, size = 65536,
first = 0x0, last = 0x0}, async_ready = {need_thr_prgr = 0, thr_prgr = 0,
queue = 0x0}, delayed_wakeup = {next = 0, sched2jix = 0x0, jix = 0,
job = 0x0}, debug = {wait_completed = {flags = 0, callback = 0x0,
arg = 0x0}}}
{port_specs, [
{"priv/niftest.so", [
"c_src/*.c"
]}
]}.
{eunit_opts, [
{smp, enable},
verbose
]}.
{application, niftest, [
{description, "NIF Test"},
{vsn, git},
{registered, []},
{applications, [kernel, stdlib]}
]}.
-module(niftest).
-on_load(init/0).
-export([
fun1/0
]).
-define(NOT_LOADED, not_loaded(?LINE)).
fun1() ->
?NOT_LOADED.
init() ->
PrivDir = case code:priv_dir(?MODULE) of
{error, _} ->
EbinDir = filename:dirname(code:which(?MODULE)),
AppPath = filename:dirname(EbinDir),
filename:join(AppPath, "priv");
Path ->
Path
end,
erlang:load_nif(filename:join(PrivDir, "niftest"), 0).
not_loaded(Line) ->
erlang:nif_error({not_loaded, [{module, ?MODULE}, {line, Line}]}).
-module(segfault_tests).
-include_lib("eunit/include/eunit.hrl").
do_test() ->
io:format(standard_error, "OS Pid: ~s~n", [os:getpid()]),
loop().
loop() ->
niftest:fun1(),
loop().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment