File 0691-erts-Fix-bugs-doing-HAlloc-without-process-main-lock.patch of Package erlang
From eb5915d3f46ae9ba4b1fbf7c5e650ec1a0efa444 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Mon, 20 Jan 2020 20:04:36 +0100
Subject: [PATCH] erts: Fix bugs doing HAlloc without process main lock
after erts_thr_progress_block() has been called.
Dirty schedulers may still be running NIFs
that may seize the main lock to send a message for example
and thereby potentially corrupt the heap.
---
erts/emulator/beam/beam_bif_load.c | 4 +++-
erts/emulator/beam/dist.c | 2 +-
erts/emulator/beam/erl_bif_trace.c | 5 ++---
erts/emulator/beam/erl_nif.c | 2 +-
erts/emulator/beam/erl_node_tables.c | 5 +++--
erts/emulator/beam/erl_process.c | 3 +--
6 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/erts/emulator/beam/beam_bif_load.c b/erts/emulator/beam/beam_bif_load.c
index 19b6deecea..a7d16c6f2b 100644
--- a/erts/emulator/beam/beam_bif_load.c
+++ b/erts/emulator/beam/beam_bif_load.c
@@ -377,6 +377,7 @@ finish_loading_1(BIF_ALIST_1)
/* tracing or hipe need thread blocking */
erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
+ erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
is_blocking = 1;
break;
}
@@ -464,7 +465,6 @@ staging_epilogue(Process* c_p, int commit, Eterm res, int is_blocking,
}
if (is_blocking) {
erts_thr_progress_unblock();
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
}
erts_release_code_write_permission();
return res;
@@ -661,6 +661,7 @@ BIF_RETTYPE delete_module_1(BIF_ALIST_1)
/* tracing or hipe need to go single threaded */
erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
+ erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
is_blocking = 1;
if (modp->curr.num_breakpoints) {
erts_clear_module_break(modp);
@@ -794,6 +795,7 @@ BIF_RETTYPE finish_after_on_load_2(BIF_ALIST_2)
erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
+ erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
is_blocking = 1;
}
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index bbe2fc31f3..277ac378e9 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -4379,6 +4379,7 @@ erts_processes_monitoring_nodes(Process *c_p)
erts_proc_unlock(c_p, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
+ erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
erts_mtx_lock(&nodes_monitors_mtx);
@@ -4409,7 +4410,6 @@ erts_processes_monitoring_nodes(Process *c_p)
erts_mtx_unlock(&nodes_monitors_mtx);
erts_thr_progress_unblock();
- erts_proc_lock(c_p, ERTS_PROC_LOCK_MAIN);
return ctxt.res;
}
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index b31d5b86cb..4162a6c591 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -1125,6 +1125,7 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
if ( (key == am_call_time) || (key == am_all)) {
erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
+ erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
erts_mtx_lock(&erts_dirty_bp_ix_mtx);
@@ -1134,7 +1135,6 @@ trace_info_func(Process* p, Eterm func_spec, Eterm key)
erts_mtx_unlock(&erts_dirty_bp_ix_mtx);
if ( (key == am_call_time) || (key == am_all)) {
erts_thr_progress_unblock();
- erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
switch (r) {
@@ -2194,6 +2194,7 @@ system_monitor(Process *p, Eterm monitor_pid, Eterm list)
system_blocked = 1;
erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
+ erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
if (!erts_pid2proc(p, ERTS_PROC_LOCK_MAIN, monitor_pid, 0))
goto error;
@@ -2233,7 +2234,6 @@ system_monitor(Process *p, Eterm monitor_pid, Eterm list)
erts_system_monitor_flags.busy_dist_port = !!busy_dist_port;
erts_thr_progress_unblock();
- erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
BIF_RET(prev);
}
@@ -2241,7 +2241,6 @@ system_monitor(Process *p, Eterm monitor_pid, Eterm list)
if (system_blocked) {
erts_thr_progress_unblock();
- erts_proc_lock(p, ERTS_PROC_LOCK_MAIN);
}
BIF_ERROR(p, BADARG);
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index ebef485b04..dccfd54110 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -4056,6 +4056,7 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
/* Block system (is this the right place to do it?) */
erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
+ erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
/* Find calling module */
ASSERT(BIF_P->current != NULL);
@@ -4270,7 +4271,6 @@ BIF_RETTYPE load_nif_2(BIF_ALIST_2)
}
erts_thr_progress_unblock();
- erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
erts_release_code_write_permission();
erts_free(ERTS_ALC_T_TMP, lib_name);
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 8a80ecfa87..db3b9e3d58 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1251,7 +1251,9 @@ erts_get_node_and_dist_references(struct process *proc)
erts_proc_unlock(proc, ERTS_PROC_LOCK_MAIN);
erts_thr_progress_block();
- /* No need to lock any thing since we are alone... */
+ erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
+ /* No need to lock any thing else since we are alone...
+ ... except dirty stuff... (?) */
if (references_atoms_need_init) {
INIT_AM(heap);
@@ -1296,7 +1298,6 @@ erts_get_node_and_dist_references(struct process *proc)
delete_reference_table();
erts_thr_progress_unblock();
- erts_proc_lock(proc, ERTS_PROC_LOCK_MAIN);
return res;
}
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index 912dfa6b64..718fbfe95f 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -13165,8 +13165,7 @@ erts_dbg_check_halloc_lock(Process *p)
esdp = erts_proc_sched_data(p);
if (esdp && p == esdp->match_pseudo_process)
return 1;
- if (erts_thr_progress_is_blocking())
- return 1;
+ /* erts_thr_progress_is_blocking() is not enough as dirty NIFs may run */
return 0;
}
#endif
--
2.16.4