diff options
author | Sverker Eriksson <[email protected]> | 2011-07-06 20:43:54 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2011-07-07 17:38:08 +0200 |
commit | c50b9bf4137333850e76393752495a09147e73a6 (patch) | |
tree | e62d9069924e63f79a6f6c651be1943da16c1372 | |
parent | 32fc16e311bfbc5abd0ab8caf64d566e1e65196d (diff) | |
download | otp-c50b9bf4137333850e76393752495a09147e73a6.tar.gz otp-c50b9bf4137333850e76393752495a09147e73a6.tar.bz2 otp-c50b9bf4137333850e76393752495a09147e73a6.zip |
Fix a match-spec trace bug that could cause emulator crash
A trace matchspec with 'enable_trace' or 'disable_trace' in body could
cause an emulator crash if a concurrent process altered the trace
setting of the traced function by calling erlang:trace_pattern.
The effect was a deallocation of the binary holding the matchspec
program while it was running. Fixed by increasing reference count of
ms-binary in the cases when 'enable_trace' or 'disable_trace' may
cause a system block that may alter the ongoing trace.
The paradox here is that db_prog_match() is using erts_smp_block_system()
to do 'enable_trace' and 'disable_trace' in a safe (atomic) way. But that
also have the (non-atomic) effect that racing thread might block the
system and change the trace settings with erlang:trace_pattern.
-rw-r--r-- | erts/emulator/beam/erl_db_util.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index c3b074f782..e5be1f253a 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -1731,6 +1731,7 @@ Eterm db_prog_match(Process *c_p, Binary *bprog, #define BEGIN_ATOMIC_TRACE(p) \ do { \ if (! atomic_trace) { \ + erts_refc_inc(&bprog->refc, 2); \ erts_smp_proc_unlock((p), ERTS_PROC_LOCK_MAIN); \ erts_smp_block_system(0); \ atomic_trace = !0; \ @@ -1741,6 +1742,9 @@ Eterm db_prog_match(Process *c_p, Binary *bprog, if (atomic_trace) { \ erts_smp_release_system(); \ erts_smp_proc_lock((p), ERTS_PROC_LOCK_MAIN); \ + if (erts_refc_dectest(&bprog->refc, 0) == 0) {\ + erts_bin_free(bprog); \ + } \ atomic_trace = 0; \ } \ } while (0) |