From 2be04f53570066031c4fc152aa14798dc38c0403 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Mon, 27 Sep 2021 14:09:04 +0200 Subject: Restore save pointer on bad timeout value in receive The message queue save pointer was not restored to the beginning of the message queue when a bad timeout value was encountered in the receive. If the timeout_value exception was caught, the following receive would not be searched from the beginning of the message queue. This potentially caused the process to hang forever even though a matching message was present in the message queue. --- erts/emulator/beam/msg_instrs.tab | 2 ++ erts/emulator/test/receive_SUITE.erl | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/erts/emulator/beam/msg_instrs.tab b/erts/emulator/beam/msg_instrs.tab index 10fd5ad48d..7056bbc95b 100644 --- a/erts/emulator/beam/msg_instrs.tab +++ b/erts/emulator/beam/msg_instrs.tab @@ -305,6 +305,7 @@ timeout() { TIMEOUT_VALUE() { c_p->freason = EXC_TIMEOUT_VALUE; + JOIN_MESSAGE(c_p); goto find_func_info; //| -no_next } @@ -372,6 +373,7 @@ wait.src(Src) { } else { /* Wrong time */ erts_proc_unlock(c_p, ERTS_PROC_LOCKS_MSG_RECEIVE); c_p->freason = EXC_TIMEOUT_VALUE; + JOIN_MESSAGE(c_p); goto find_func_info; } } diff --git a/erts/emulator/test/receive_SUITE.erl b/erts/emulator/test/receive_SUITE.erl index 339507c9d8..d42db517c2 100644 --- a/erts/emulator/test/receive_SUITE.erl +++ b/erts/emulator/test/receive_SUITE.erl @@ -28,7 +28,8 @@ call_with_huge_message_queue/1,receive_in_between/1, receive_opt_exception/1,receive_opt_recursion/1, receive_opt_deferred_save/1, - erl_1199/1]). + erl_1199/1, + gh_5235_missing_save_reset/1]). suite() -> [{ct_hooks,[ts_install_cth]}, @@ -40,7 +41,8 @@ all() -> receive_opt_exception, receive_opt_recursion, receive_opt_deferred_save, - erl_1199]. + erl_1199, + gh_5235_missing_save_reset]. init_per_testcase(receive_opt_deferred_save, Config) -> case erlang:system_info(schedulers) of @@ -396,10 +398,36 @@ erl_1199_flush_blipp() -> ok end. +gh_5235_missing_save_reset(Config) when is_list(Config) -> + %% + %% Used to hang in the second receive due to save + %% pointer not being reset on bad timeout value... + %% + ct:timetrap({seconds, 10}), + id(self()) ! init, + try + receive blipp -> ok after blupp -> ok end + catch _:_ -> + ok + end, + receive init -> ok end, + + %% Try with a timeout value not known in compile + %% time as well... + id(self()) ! init2, + try + receive blapp -> ok after id(blepp) -> ok end + catch _:_ -> + ok + end, + receive init2 -> ok end. + %%% %%% Common helpers. %%% +id(X) -> X. + echo_loop() -> receive {Ref,{Pid,Msg}} -> -- cgit v1.2.1