From c4862a5419018a8c985dab348a44d5811464df15 Mon Sep 17 00:00:00 2001
From: Rickard Green <rickard@erlang.org>
Date: Wed, 17 Jul 2019 14:24:18 +0200
Subject: Fix node refc test for system message queue

---
 erts/emulator/beam/erl_node_tables.c |  2 +-
 erts/emulator/beam/erl_trace.c       | 62 +++++++++++++++++++++---------------
 erts/emulator/beam/erl_trace.h       |  8 ++---
 3 files changed, 42 insertions(+), 30 deletions(-)

(limited to 'erts')

diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index deadf435e9..dc77b7d77b 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -1431,7 +1431,7 @@ setup_reference_table(void)
     }
     
 #ifdef ERTS_SMP
-    erts_foreach_sys_msg_in_q(insert_sys_msg);
+    erts_debug_foreach_sys_msg_in_q(insert_sys_msg);
 #endif
 
     /* Insert all ports */
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index 9fda4ff6ff..59229671e3 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -2411,17 +2411,20 @@ sys_msg_dispatcher_wait(void *vwait_p)
     erts_smp_mtx_unlock(&smq_mtx);
 }
 
+static ErtsSysMsgQ *local_sys_message_queue = NULL;
+
 static void *
 sys_msg_dispatcher_func(void *unused)
 {
     ErtsThrPrgrCallbacks callbacks;
-    ErtsSysMsgQ *local_sys_message_queue = NULL;
     int wait = 0;
 
 #ifdef ERTS_ENABLE_LOCK_CHECK
     erts_lc_set_thread_name("system message dispatcher");
 #endif
 
+    local_sys_message_queue = NULL;
+
     callbacks.arg = (void *) &wait;
     callbacks.wakeup = sys_msg_dispatcher_wakeup;
     callbacks.prepare_wait = sys_msg_dispatcher_prep_wait;
@@ -2478,6 +2481,8 @@ sys_msg_dispatcher_func(void *unused)
 	    Process *proc = NULL;
 	    Port *port = NULL;
 
+            ASSERT(is_value(smqp->msg));
+
 	    if (erts_thr_progress_update(NULL))
 		erts_thr_progress_leader_update(NULL);
 
@@ -2580,6 +2585,7 @@ sys_msg_dispatcher_func(void *unused)
 		erts_fprintf(stderr, "dropped\n");
 #endif
 	    }
+            smqp->msg = THE_NON_VALUE;
 	}
     }
 
@@ -2587,32 +2593,38 @@ sys_msg_dispatcher_func(void *unused)
 }
 
 void
-erts_foreach_sys_msg_in_q(void (*func)(Eterm,
-				       Eterm,
-				       Eterm,
-				       ErlHeapFragment *))
+erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm,
+                                             Eterm,
+                                             Eterm,
+                                             ErlHeapFragment *))
 {
-    ErtsSysMsgQ *sm;
-    erts_smp_mtx_lock(&smq_mtx);
-    for (sm = sys_message_queue; sm; sm = sm->next) {
-	Eterm to;
-	switch (sm->type) {
-	case SYS_MSG_TYPE_SYSMON:
-	    to = erts_get_system_monitor();
-	    break;
-	case SYS_MSG_TYPE_SYSPROF:
-	    to = erts_get_system_profile();
-	    break;
-	case SYS_MSG_TYPE_ERRLGR:
-	    to = am_error_logger;
-	    break;
-	default:
-	    to = NIL;
-	    break;
-	}
-	(*func)(sm->from, to, sm->msg, sm->bp);
+    ErtsSysMsgQ *smq[] = {sys_message_queue, local_sys_message_queue};
+    int i;
+
+    ERTS_LC_ASSERT(erts_thr_progress_is_blocking());
+
+    for (i = 0; i < sizeof(smq)/sizeof(smq[0]); i++) {
+        ErtsSysMsgQ *sm;
+        for (sm = smq[i]; sm; sm = sm->next) {
+            Eterm to;
+            switch (sm->type) {
+            case SYS_MSG_TYPE_SYSMON:
+                to = erts_get_system_monitor();
+                break;
+            case SYS_MSG_TYPE_SYSPROF:
+                to = erts_get_system_profile();
+                break;
+            case SYS_MSG_TYPE_ERRLGR:
+                to = am_error_logger;
+                break;
+            default:
+                to = NIL;
+                break;
+            }
+            if (is_value(sm->msg))
+                (*func)(sm->from, to, sm->msg, sm->bp);
+        }
     }
-    erts_smp_mtx_unlock(&smq_mtx);
 }
 
 
diff --git a/erts/emulator/beam/erl_trace.h b/erts/emulator/beam/erl_trace.h
index 01fe1e5e23..7b764dcfe4 100644
--- a/erts/emulator/beam/erl_trace.h
+++ b/erts/emulator/beam/erl_trace.h
@@ -91,10 +91,10 @@ int erts_is_tracer_valid(Process* p);
 void erts_check_my_tracer_proc(Process *);
 void erts_block_sys_msg_dispatcher(void);
 void erts_release_sys_msg_dispatcher(void);
-void erts_foreach_sys_msg_in_q(void (*func)(Eterm,
-					    Eterm,
-					    Eterm,
-					    ErlHeapFragment *));
+void erts_debug_foreach_sys_msg_in_q(void (*func)(Eterm,
+                                                  Eterm,
+                                                  Eterm,
+                                                  ErlHeapFragment *));
 void erts_queue_error_logger_message(Eterm, Eterm, ErlHeapFragment *);
 void erts_send_sys_msg_proc(Eterm, Eterm, Eterm, ErlHeapFragment *);
 #endif
-- 
cgit v1.2.3