diff options
author | Rickard Green <[email protected]> | 2011-11-13 21:43:11 +0100 |
---|---|---|
committer | Rickard Green <[email protected]> | 2011-11-13 21:43:11 +0100 |
commit | 6ff77abac7d54f23e5a5fc465c3746c9cd7ee57b (patch) | |
tree | ae726aa920f16036d58278c6fff8e91877eaf5a7 | |
parent | 32ef224c9769cd9359496953075e0133358ccf86 (diff) | |
parent | 6214fde94809079d1764e4273886544272784eb3 (diff) | |
download | otp-6ff77abac7d54f23e5a5fc465c3746c9cd7ee57b.tar.gz otp-6ff77abac7d54f23e5a5fc465c3746c9cd7ee57b.tar.bz2 otp-6ff77abac7d54f23e5a5fc465c3746c9cd7ee57b.zip |
Merge branch 'rickard/multi-exit-bug/OTP-9705'
* rickard/multi-exit-bug/OTP-9705:
Make sure only one thread exits the runtime system
-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 9a09f08618..7c047891d9 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; @@ -646,6 +648,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 @@ -1506,6 +1509,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 @@ -1570,10 +1596,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) @@ -1610,10 +1636,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) |