From 2a46ca2dbe1410c1e7ce057051cdb65526a87485 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 21 Dec 2018 10:36:08 +0100 Subject: erts: Make sure to take main lock when dumping proc info If the main lock is not taken then any process running on a dirty scheduler may cause all kinds of problems. --- erts/emulator/beam/break.c | 41 +++++++++++++++++++++++++++++++-------- erts/emulator/beam/erl_bif_info.c | 1 + erts/emulator/beam/erl_db_util.c | 2 +- erts/emulator/beam/global.h | 2 +- 4 files changed, 36 insertions(+), 10 deletions(-) (limited to 'erts/emulator') diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c index 9ff52c92b8..92009c2345 100644 --- a/erts/emulator/beam/break.c +++ b/erts/emulator/beam/break.c @@ -82,7 +82,7 @@ process_info(fmtfn_t to, void *to_arg) * they are most likely just created and has invalid data */ if (!ERTS_PROC_IS_EXITING(p) && p->heap != NULL) - print_process_info(to, to_arg, p); + print_process_info(to, to_arg, p, 0); } } @@ -101,7 +101,7 @@ process_killer(void) rp = erts_pix2proc(i); if (rp && rp->i != ENULL) { int br; - print_process_info(ERTS_PRINT_STDOUT, NULL, rp); + print_process_info(ERTS_PRINT_STDOUT, NULL, rp, 0); erts_printf("(k)ill (n)ext (r)eturn:\n"); while(1) { if ((j = sys_get_key(0)) <= 0) @@ -199,13 +199,14 @@ static void doit_print_monitor(ErtsMonitor *mon, void *vpcontext) /* Display info about an individual Erlang process */ void -print_process_info(fmtfn_t to, void *to_arg, Process *p) +print_process_info(fmtfn_t to, void *to_arg, Process *p, ErtsProcLocks orig_locks) { int garbing = 0; int running = 0; Sint len; struct saved_calls *scb; erts_aint32_t state; + ErtsProcLocks locks = orig_locks; /* display the PID */ erts_print(to, to_arg, "=proc:%T\n", p->common.id); @@ -222,6 +223,22 @@ print_process_info(fmtfn_t to, void *to_arg, Process *p) | ERTS_PSFLG_DIRTY_RUNNING)) running = 1; + if (!(locks & ERTS_PROC_LOCK_MAIN)) { + locks |= ERTS_PROC_LOCK_MAIN; + if (ERTS_IS_CRASH_DUMPING && running) { + if (erts_proc_trylock(p, locks)) { + /* crash dumping and main lock taken, this probably means that + the process is doing a GC on a dirty-scheduler... so we cannot + do erts_proc_sig_fetch as that would potentially cause a segfault */ + locks = 0; + } + } else { + erts_proc_lock(p, locks); + } + } else { + ERTS_ASSERT(locks == ERTS_PROC_LOCK_MAIN && "Only main lock should be held"); + } + /* * If the process is registered as a global process, display the * registered name @@ -251,13 +268,19 @@ print_process_info(fmtfn_t to, void *to_arg, Process *p) erts_print(to, to_arg, "Spawned by: %T\n", p->parent); - erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ); - len = erts_proc_sig_fetch(p); - erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ); + if (locks & ERTS_PROC_LOCK_MAIN) { + erts_proc_lock(p, ERTS_PROC_LOCK_MSGQ); + len = erts_proc_sig_fetch(p); + erts_proc_unlock(p, ERTS_PROC_LOCK_MSGQ); + } else { + len = p->sig_qs.len; + } erts_print(to, to_arg, "Message queue length: %d\n", len); - /* display the message queue only if there is anything in it */ - if (!ERTS_IS_CRASH_DUMPING && p->sig_qs.first != NULL && !garbing) { + /* display the message queue only if there is anything in it + and we can do it safely */ + if (!ERTS_IS_CRASH_DUMPING && p->sig_qs.first != NULL && !garbing + && (locks & ERTS_PROC_LOCK_MAIN)) { erts_print(to, to_arg, "Message queue: ["); ERTS_FOREACH_SIG_PRIVQS( p, mp, @@ -357,6 +380,8 @@ print_process_info(fmtfn_t to, void *to_arg, Process *p) /* Display all states */ erts_print(to, to_arg, "Internal State: "); erts_dump_extended_process_state(to, to_arg, state); + + erts_proc_unlock(p, locks & ~orig_locks); } static void diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c index 9cc95a5c09..6137edef1b 100644 --- a/erts/emulator/beam/erl_bif_info.c +++ b/erts/emulator/beam/erl_bif_info.c @@ -4610,6 +4610,7 @@ BIF_RETTYPE erts_debug_set_internal_state_2(BIF_ALIST_2) } } else if (ERTS_IS_ATOM_STR("broken_halt", BIF_ARG_1)) { + erts_proc_unlock(BIF_P, ERTS_PROC_LOCK_MAIN); broken_halt_test(BIF_ARG_2); } else if (ERTS_IS_ATOM_STR("unique_monotonic_integer_state", BIF_ARG_1)) { diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c index f1d47326b4..e2c029c244 100644 --- a/erts/emulator/beam/erl_db_util.c +++ b/erts/emulator/beam/erl_db_util.c @@ -2470,7 +2470,7 @@ restart: case matchProcessDump: { erts_dsprintf_buf_t *dsbufp = erts_create_tmp_dsbuf(0); ASSERT(c_p == self); - print_process_info(ERTS_PRINT_DSBUF, (void *) dsbufp, c_p); + print_process_info(ERTS_PRINT_DSBUF, (void *) dsbufp, c_p, ERTS_PROC_LOCK_MAIN); *esp++ = new_binary(build_proc, (byte *)dsbufp->str, dsbufp->str_len); erts_destroy_tmp_dsbuf(dsbufp); diff --git a/erts/emulator/beam/global.h b/erts/emulator/beam/global.h index f1c6adeedd..36b753ca9c 100644 --- a/erts/emulator/beam/global.h +++ b/erts/emulator/beam/global.h @@ -962,7 +962,7 @@ void init_break_handler(void); void erts_set_ignore_break(void); void erts_replace_intr(void); void process_info(fmtfn_t, void *); -void print_process_info(fmtfn_t, void *, Process*); +void print_process_info(fmtfn_t, void *, Process*, ErtsProcLocks); void info(fmtfn_t, void *); void loaded(fmtfn_t, void *); void erts_print_base64(fmtfn_t to, void *to_arg, byte* src, Uint size); -- cgit v1.2.3