diff options
author | Sverker Eriksson <[email protected]> | 2017-01-12 13:58:26 +0100 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2017-01-12 13:58:26 +0100 |
commit | af5169d85fcd545e3c857a219db081a62f33404d (patch) | |
tree | a08ad74d060311ada3b11b76fd419a1d01e32415 /erts/emulator/beam/beam_load.c | |
parent | 2b41d8f318b7e5ec139d42fd2f01a132699be839 (diff) | |
download | otp-af5169d85fcd545e3c857a219db081a62f33404d.tar.gz otp-af5169d85fcd545e3c857a219db081a62f33404d.tar.bz2 otp-af5169d85fcd545e3c857a219db081a62f33404d.zip |
erts: Fix race bug between export fun creation and code loading
Symptom: SEGV crash on ARM in delete_code() -> export_list().
Could probably happen on other machines as well.
Problem: Staging export table was iterated in an unsafe way
while an entry was added for a new export fun.
Solution: Correct write order and some memory barriers.
Diffstat (limited to 'erts/emulator/beam/beam_load.c')
-rw-r--r-- | erts/emulator/beam/beam_load.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c index 0afdedf6c2..3f2bdf3f9d 100644 --- a/erts/emulator/beam/beam_load.c +++ b/erts/emulator/beam/beam_load.c @@ -797,14 +797,14 @@ erts_finish_loading(Binary* magic, Process* c_p, } else { ErtsCodeIndex code_ix = erts_staging_code_ix(); Eterm module = stp->module; - int i; + int i, num_exps; /* * There is an -on_load() function. We will keep the current * code, but we must turn off any tracing. */ - - for (i = 0; i < export_list_size(code_ix); i++) { + num_exps = export_list_size(code_ix); + for (i = 0; i < num_exps; i++) { Export *ep = export_list(i, code_ix); if (ep == NULL || ep->code[0] != module) { continue; @@ -5754,12 +5754,13 @@ exported_from_module(Process* p, /* Process whose heap to use. */ ErtsCodeIndex code_ix, Eterm mod) /* Tagged atom for module. */ { - int i; + int i, num_exps; Eterm* hp = NULL; Eterm* hend = NULL; Eterm result = NIL; - for (i = 0; i < export_list_size(code_ix); i++) { + num_exps = export_list_size(code_ix); + for (i = 0; i < num_exps; i++) { Export* ep = export_list(i,code_ix); if (ep->code[0] == mod) { |