From 23f132d9ab776ab94c29f1faed76c9fde8f4a73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 29 May 2017 14:41:14 +0200 Subject: Make sure that asynchronous replies are not lost If an synchronous GC was requested by calling: erlang:garbage_collect(Pid, [{async,Ref}]) the reply message could in certain circumstances be lost. The problem is in cleanup_sys_tasks() in erl_process.c. If there were at least one dirty task, only the first dirty task would be cleaned up. All other systems tasks would not be cleaned up (that is, no replies would be sent to other processes waiting for the tasks to finish). --- erts/emulator/beam/erl_process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 7952e3031d..0575729bbd 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -11331,7 +11331,9 @@ cleanup_sys_tasks(Process *c_p, erts_aint32_t in_state, int in_reds) erts_aint32_t state = in_state; int max_reds = in_reds; int reds = 0; - int qmask = 0; + int qmask = 1; /* Set to 1 to force looping as long as there + * are dirty tasks. + */ ERTS_SMP_LC_ASSERT(erts_proc_lc_my_proc_locks(c_p) == ERTS_PROC_LOCK_MAIN); -- cgit v1.2.3 From c819af0538083d861e8bd8ba66768f5e5a633311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Gustavsson?= Date: Mon, 29 May 2017 14:51:01 +0200 Subject: erl_process.c: Add more assertions in process termination Before terminating a process, add assertions to make sure that all queues for system tasks have been emptied. --- erts/emulator/beam/erl_process.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index 0575729bbd..d4385e3987 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -13937,6 +13937,16 @@ erts_continue_exit_process(Process *p) goto yield; } +#ifdef DEBUG + erts_smp_proc_lock(p, ERTS_PROC_LOCK_STATUS); + ASSERT(p->sys_task_qs == NULL); + ASSERT(ERTS_PROC_GET_DELAYED_GC_TASK_QS(p) == NULL); +#ifdef ERTS_DIRTY_SCHEDULERS + ASSERT(p->dirty_sys_tasks == NULL); +#endif + erts_smp_proc_unlock(p, ERTS_PROC_LOCK_STATUS); +#endif + if (p->flags & F_USING_DDLL) { erts_ddll_proc_dead(p, ERTS_PROC_LOCK_MAIN); p->flags &= ~F_USING_DDLL; -- cgit v1.2.3