From 2a46ca2dbe1410c1e7ce057051cdb65526a87485 Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
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(-)

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


From 6f8bb9b6fb5dc6bda960a95b36274f84e1b6330c Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Fri, 21 Dec 2018 10:37:33 +0100
Subject: erts: Remove dead gdb functions from code

---
 erts/emulator/beam/utils.c | 55 ----------------------------------------------
 1 file changed, 55 deletions(-)

diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 1a6bcbb66e..a231638b50 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -4788,58 +4788,3 @@ erts_ptr_id(void *ptr)
     return ptr;
 }
 
-#ifdef DEBUG
-/*
- * Handy functions when using a debugger - don't use in the code!
- */
-
-void upp(byte *buf, size_t sz)
-{
-    bin_write(ERTS_PRINT_STDERR, NULL, buf, sz);
-}
-
-void pat(Eterm atom)
-{
-    upp(atom_tab(atom_val(atom))->name,
-	atom_tab(atom_val(atom))->len);
-}
-
-
-void pinfo()
-{
-    process_info(ERTS_PRINT_STDOUT, NULL);
-}
-
-
-void pp(p)
-Process *p;
-{
-    if(p)
-	print_process_info(ERTS_PRINT_STDERR, NULL, p);
-}
-
-void ppi(Eterm pid)
-{
-    pp(erts_proc_lookup(pid));
-}
-
-void td(Eterm x)
-{
-    erts_fprintf(stderr, "%T\n", x);
-}
-
-void
-ps(Process* p, Eterm* stop)
-{
-    Eterm* sp = STACK_START(p) - 1;
-
-    if (stop <= STACK_END(p)) {
-        stop = STACK_END(p) + 1;
-    }
-
-    while(sp >= stop) {
-	erts_printf("%p: %.75T\n", sp, *sp);
-	sp--;
-    }
-}
-#endif
-- 
cgit v1.2.3