diff options
author | Eric Avdey <eiri@eiri.ca> | 2017-12-20 16:44:33 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-20 16:44:33 -0400 |
commit | 3b28b84da610114626fb6c1f83e44ae874e33d8b (patch) | |
tree | eaa8268d708796ffa02044d26e2b1ca338723526 | |
parent | 7c37e5863905185902f2e07dc8ce0d3019df34e4 (diff) | |
download | couchdb-3b28b84da610114626fb6c1f83e44ae874e33d8b.tar.gz |
Fix mango native proc crash (#1067)
Don't crash on receiving cast stop
When soft limit is reached couch_proc_manager
evicts idle processes by casting on them `stop`
message. Since mango_native_proc doesn't handle
this message it results to its crash with
`invalid_cast` reason.
-rw-r--r-- | src/mango/src/mango_idx_text.erl | 2 | ||||
-rw-r--r-- | src/mango/src/mango_native_proc.erl | 36 |
2 files changed, 36 insertions, 2 deletions
diff --git a/src/mango/src/mango_idx_text.erl b/src/mango/src/mango_idx_text.erl index 369e2cd08..29b4441a1 100644 --- a/src/mango/src/mango_idx_text.erl +++ b/src/mango/src/mango_idx_text.erl @@ -330,7 +330,7 @@ indexable_fields(Fields, {op_not, {ExistsQuery, Arg}}) when is_tuple(Arg) -> Fields0 = indexable_fields(Fields, ExistsQuery), indexable_fields(Fields0, Arg); % forces "$exists" : false to use _all_docs -indexable_fields(Fields, {op_not, {ExistsQuery, false}}) -> +indexable_fields(_, {op_not, {_, false}}) -> []; indexable_fields(Fields, {op_insert, Arg}) when is_binary(Arg) -> diff --git a/src/mango/src/mango_native_proc.erl b/src/mango/src/mango_native_proc.erl index 61d79b7ec..7a3420193 100644 --- a/src/mango/src/mango_native_proc.erl +++ b/src/mango/src/mango_native_proc.erl @@ -113,6 +113,9 @@ handle_cast(garbage_collect, St) -> erlang:garbage_collect(), {noreply, St}; +handle_cast(stop, St) -> + {stop, normal, St}; + handle_cast(Msg, St) -> {stop, {invalid_cast, Msg}, St}. @@ -363,4 +366,35 @@ validate_index_info(IndexInfo) -> [invalid_index | Results0] end end, [], IdxTypes), - lists:member(valid_index, Results).
\ No newline at end of file + lists:member(valid_index, Results). + + +-ifdef(TEST). + +-include_lib("eunit/include/eunit.hrl"). + +handle_garbage_collect_cast_test() -> + Pid = self(), + {_, TracerRef} = spawn_monitor(fun() -> + erlang:trace(Pid, true, [garbage_collection]), + receive {trace, Pid, gc_start, _} -> + erlang:trace(Pid, false, [garbage_collection]), + exit(gc_start) + end + end), + erlang:yield(), + ?assertEqual({noreply, []}, handle_cast(garbage_collect, [])), + receive + {'DOWN', TracerRef, _, _, Msg} -> ?assertEqual(gc_start, Msg) + after 1000 -> + erlang:error({assertion_failed, [{module, ?MODULE}, {line, ?LINE}, + {expected, gc_start}, {reason, timeout}]}) + end. + +handle_stop_cast_test() -> + ?assertEqual({stop, normal, []}, handle_cast(stop, [])). + +handle_invalid_cast_test() -> + ?assertEqual({stop, {invalid_cast, random}, []}, handle_cast(random, [])). + +-endif. |