summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Avdey <eiri@eiri.ca>2017-12-20 16:44:33 -0400
committerGitHub <noreply@github.com>2017-12-20 16:44:33 -0400
commit3b28b84da610114626fb6c1f83e44ae874e33d8b (patch)
treeeaa8268d708796ffa02044d26e2b1ca338723526
parent7c37e5863905185902f2e07dc8ce0d3019df34e4 (diff)
downloadcouchdb-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.erl2
-rw-r--r--src/mango/src/mango_native_proc.erl36
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.