diff options
author | Rickard Green <[email protected]> | 2011-11-11 19:18:36 +0100 |
---|---|---|
committer | Rickard Green <[email protected]> | 2011-11-13 20:40:59 +0100 |
commit | 6214fde94809079d1764e4273886544272784eb3 (patch) | |
tree | 9fde50efb1f6bd618314ac7e42e304cf78326978 /erts/emulator | |
parent | 15774d2ac5ba38dba287309f91eb7e4f58b9a636 (diff) | |
download | otp-6214fde94809079d1764e4273886544272784eb3.tar.gz otp-6214fde94809079d1764e4273886544272784eb3.tar.bz2 otp-6214fde94809079d1764e4273886544272784eb3.zip |
Make sure only one thread exits the runtime system
The runtime system crashed if more than one thread tried to exit
the runtime system at the same time.
Diffstat (limited to 'erts/emulator')
-rw-r--r-- | erts/emulator/beam/erl_init.c | 34 |
1 files changed, 30 insertions, 4 deletions
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c index 98b997583c..05fa10964a 100644 --- a/erts/emulator/beam/erl_init.c +++ b/erts/emulator/beam/erl_init.c @@ -71,6 +71,8 @@ static void erl_init(int ncpu); #define ERTS_MIN_COMPAT_REL 7 +static erts_atomic_t exiting; + #ifdef ERTS_SMP erts_smp_atomic32_t erts_writing_erl_crash_dump; erts_tsd_key_t erts_is_crash_dumping_key; @@ -644,6 +646,7 @@ early_init(int *argc, char **argv) /* erts_use_r9_pids_ports = 0; erts_sys_pre_init(); + erts_atomic_init_nob(&exiting, 0); #ifdef ERTS_SMP erts_thr_progress_pre_init(); #endif @@ -1502,6 +1505,29 @@ __decl_noreturn void erts_thr_fatal_error(int err, char *what) static void system_cleanup(int exit_code) { + /* + * Make sure only one thread exits the runtime system. + */ + if (erts_atomic_inc_read_nob(&exiting) != 1) { + /* + * Another thread is currently exiting the system; + * wait for it to do its job. + */ +#ifdef ERTS_SMP + if (erts_thr_progress_is_managed_thread()) { + /* + * The exiting thread might be waiting for + * us to block; need to update status... + */ + erts_thr_progress_active(NULL, 0); + erts_thr_progress_prepare_wait(NULL); + } +#endif + /* Wait forever... */ + while (1) + erts_milli_sleep(10000000); + } + /* No cleanup wanted if ... * 1. we are about to do an abnormal exit * 2. we haven't finished initializing, or @@ -1566,10 +1592,10 @@ __decl_noreturn void erl_exit0(char *file, int line, int n, char *fmt,...) va_start(args, fmt); - save_statistics(); - system_cleanup(n); + save_statistics(); + an = abs(n); if (erts_mtrace_enabled) @@ -1606,10 +1632,10 @@ __decl_noreturn void erl_exit(int n, char *fmt,...) va_start(args, fmt); - save_statistics(); - system_cleanup(n); + save_statistics(); + an = abs(n); if (erts_mtrace_enabled) |