A minimal reproducing test case for a segfault with NIFs and dirty schedulers.
To reproduce:
$ rebar compile eunit
Machine Specifics
| diff --git a/apps/couch/src/couch_btree.erl b/apps/couch/src/couch_btree.erl | |
| index 36c2553..e76a485 100644 | |
| --- a/apps/couch/src/couch_btree.erl | |
| +++ b/apps/couch/src/couch_btree.erl | |
| @@ -348,27 +348,34 @@ complete_root(Bt, KPs) -> | |
| % written. | |
| chunkify(InList) -> | |
| - BaseChunkSize = list_to_integer(config:get("couchdb", | |
| - "btree_chunk_size", "1279")), |
| % The lock counting VM is the same except for being built with | |
| % --enable-lock-counting | |
| (dbcore@db1.cluster.name.goes.here)3> erlang:system_info(system_version). | |
| "Erlang/OTP 17 [erts-6.4] [source] [64-bit] [smp:24:24] [async-threads:32] [hipe] [kernel-poll:true]\n" | |
| % These were captured after the test and back on the non | |
| % lock counting emulator just to show a rough estimate on | |
| % reductions and proc counts for this node. | |
| (dbcore@db1.cluster.name.goes.here)2> erlang:statistics(reductions). |
| group_replies([], Revs) -> | |
| Revs; | |
| group_replies([Reply | Rest], Revs) -> | |
| group_replies(Rest, group_reply(Reply, Revs)). | |
| group_reply({ok, #doc{}} = Reply, Revs) -> | |
| {Pos, [RevId | _]} = Doc#doc.revs, | |
| add_reply({Pos, RevId}, Reply, Revs); |
| 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; | |
| } | |
| return 0; |
| #0 0x00007f41b544a107 in __GI_raise (sig=sig@entry=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 | |
| #1 0x00007f41b544b4e8 in __GI_abort () at abort.c:89 | |
| #2 0x000000000055cce3 in lc_abort () at beam/erl_lock_check.c:676 | |
| #3 0x000000000055ce15 in erts_lc_assert_failed (file=0x6de020 "beam/erl_ptab.c", line=674, | |
| assertion=0x6de3e8 "erts_thr_progress_is_managed_thread()") at beam/erl_lock_check.c:709 | |
| #4 0x00000000005b1606 in erts_ptab_delete_element (ptab=0x9a2700 <erts_proc>, ptab_el=0x7f41b4a41bc0) at beam/erl_ptab.c:674 | |
| #5 0x00000000004e9078 in erts_continue_exit_process (p=0x7f41b4a41bc0) at beam/erl_process.c:11973 | |
| #6 0x00000000004e8c20 in erts_do_exit_process (p=0x7f41b4a41bc0, reason=17355) at beam/erl_process.c:11853 | |
| #7 0x00000000005d5ce8 in terminate_proc (c_p=0x7f41b4a41bc0, Value=17355) at beam/beam_emu.c:5513 | |
| #8 0x00000000005d567c in handle_error (c_p=0x7f41b4a41bc0, pc=0x0, reg=0x7f41b4ed0440, bf=0x0) at beam/beam_emu.c:5388 |
| all: compile | |
| compile: | |
| c++ -std=c++11 -I/usr/local/include -L/usr/local/lib -ltks -ltsp -o toadtest toadtest.cc | |
| run: | |
| ./toadtest |
| diff --git a/src/couch_index_updater.erl b/src/couch_index_updater.erl | |
| index ad48f40..7153248 100644 | |
| --- a/src/couch_index_updater.erl | |
| +++ b/src/couch_index_updater.erl | |
| @@ -94,7 +94,7 @@ handle_info({'EXIT', _, {updated, Pid, IdxState}}, #st{pid=Pid}=State) -> | |
| Args = [Mod:get(db_name, IdxState), Mod:get(idx_name, IdxState)], | |
| couch_log:info("Index update finished for db: ~s idx: ~s", Args), | |
| ok = gen_server:cast(State#st.idx, {updated, IdxState}), | |
| - {noreply, State#st{pid=undefined}}; | |
| + {noreply, State#st{pid=maybe_restart_updater(IdxState)}}; |
| diff --git a/test/javascript/run b/test/javascript/run | |
| index 4c71204..268e430 100755 | |
| --- a/test/javascript/run | |
| +++ b/test/javascript/run | |
| @@ -71,7 +71,7 @@ def mkformatter(tests): | |
| def run_couchjs(test, fmt): | |
| fmt(test) | |
| - cmd = [COUCHJS, "-H"] + SCRIPTS + [test, RUNNER] | |
| + cmd = [COUCHJS, "-H", "-T"] + SCRIPTS + [test, RUNNER] |
| [log] | |
| ; Set the log writer to use, currently known writers are: | |
| ; stderr | |
| ; file | |
| ; syslog | |
| writer = stderr | |
| ; Options for the file writer | |
| ; file = couch.log | |
| ; write_buffer = 16384 ; bytes |