File 1500-erts-Fix-bug-in-erlang-trace-3-when-called-for-all-p.patch of Package erlang

From 026c2bd3e8746d13f1f20ca42916814961ce80e9 Mon Sep 17 00:00:00 2001
From: Sverker Eriksson <sverker@erlang.org>
Date: Tue, 19 Mar 2024 16:14:09 +0100
Subject: [PATCH 2/2] erts: Fix bug in erlang:trace/3 when called for all
 processes or ports.

Calling erlang:trace/3 with first argument one of [ports, processes,
existing_ports, existing_processes, existing, all], could cause
emulator crash if a dirty scheduler was executing a simultaneous
trace action.
---
 erts/emulator/beam/erl_bif_trace.c | 23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)

diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index 8e834e9c3c..cd8323d4d5 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -502,11 +502,15 @@ start_trace(Process *c_p, ErtsTracer tracer,
        In the code below port is used for both proc and port */
     Port *port = (Port*)common;
 
-    /*
-     * SMP build assumes that either system is blocked or:
-     * * main lock is held on c_p
-     * * all locks are held on port common
-     */
+#ifdef ERTS_ENABLE_LOCK_CHECK
+    if (is_internal_pid(common->id)) {
+        ERTS_LC_ASSERT(erts_proc_lc_my_proc_locks((Process*)common)
+                       == ERTS_PROC_LOCKS_ALL);
+    } else {
+        ASSERT(is_internal_port(common->id));
+        ERTS_LC_ASSERT(erts_lc_is_port_locked(port));
+    }
+#endif
 
     if (!ERTS_TRACER_IS_NIL(tracer)) {
         if ((ERTS_TRACE_FLAGS(port) & TRACEE_FLAGS)
@@ -705,6 +709,11 @@ Eterm erts_internal_trace_3(BIF_ALIST_3)
 	    erts_proc_unlock(p, ERTS_PROC_LOCK_MAIN);
 	    erts_thr_progress_block();
 	    system_blocked = 1;
+            /*
+             * This will not block dirty schedulers, so we still need to lock
+             * each process/port tracee when modifying their trace settings
+             * below.
+             */
 
 	    ok = 1;
 	    if (procs || mods) {
@@ -714,8 +723,10 @@ Eterm erts_internal_trace_3(BIF_ALIST_3)
 		    Process* tracee_p = erts_pix2proc(i);
 		    if (! tracee_p) 
 			continue;
+                    erts_proc_lock(tracee_p, ERTS_PROC_LOCKS_ALL);
                     if (!start_trace(p, tracer, &tracee_p->common, on, mask))
                         matches++;
+                    erts_proc_unlock(tracee_p, ERTS_PROC_LOCKS_ALL);
 		}
 	    }
 	    if (ports || mods) {
@@ -729,8 +740,10 @@ Eterm erts_internal_trace_3(BIF_ALIST_3)
 		    state = erts_atomic32_read_nob(&tracee_port->state);
 		    if (state & ERTS_PORT_SFLGS_DEAD)
 			continue;
+                    erts_port_lock(tracee_port);
                     if (!start_trace(p, tracer, &tracee_port->common, on, mask))
                         matches++;
+                    erts_port_release(tracee_port);
 		}
 	    }
 	}
-- 
2.35.3

openSUSE Build Service is sponsored by