This is an automated email from the ASF dual-hosted git repository.

wilfred-s pushed a commit to branch branch-1.9
in repository https://gitbox.apache.org/repos/asf/yunikorn-core.git


The following commit(s) were added to refs/heads/branch-1.9 by this push:
     new 4886d4e0 [YUNIKORN-3296] Fix race between AddEvent and Stop (#1093)
4886d4e0 is described below

commit 4886d4e0dac6c622681bd87b63d01c7b9e206c0d
Author: Venkateshwaran Shanmugham <[email protected]>
AuthorDate: Mon Jun 22 15:22:22 2026 +1000

    [YUNIKORN-3296] Fix race between AddEvent and Stop (#1093)
    
    Stop() closes and clears ec.channel while holding the event system mutex.
    AddEvent() previously accessed ec.channel without synchronization. During
    TestSchedulerRecoveryQuotaPreemption, scheduler go-routines could still emit
    events while StopAll() shut down the event system, resulting in a race
    detected by go test -race.
    
    The reported race was between:
    
    EventSystemImpl.AddEvent()
    EventSystemImpl.Stop() (close(ec.channel) / ec.channel = nil)
    
    This race could also lead to a send on closed channel panic.
    
    Closes: #1093
    
    Signed-off-by: Venkateshwaran Shanmugham <[email protected]>
    Signed-off-by: Wilfred Spiegelenburg <[email protected]>
    (cherry picked from commit 20c6c151b54916a54e73af1cc2475a1b895a994b)
---
 pkg/events/event_system.go      | 13 +++++++++++++
 pkg/events/event_system_test.go | 29 +++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/pkg/events/event_system.go b/pkg/events/event_system.go
index 3306beaf..117669e1 100644
--- a/pkg/events/event_system.go
+++ b/pkg/events/event_system.go
@@ -220,6 +220,10 @@ func (ec *EventSystemImpl) Stop() {
        ec.stopped = true
 }
 
+func (ec *EventSystemImpl) isStopped() bool {
+       return ec.stopped || ec.channel == nil
+}
+
 // AddEvent adds an event record to the event system. See the interface for 
details.
 func (ec *EventSystemImpl) AddEvent(event *si.EventRecord) {
        if event != nil {
@@ -227,6 +231,15 @@ func (ec *EventSystemImpl) AddEvent(event *si.EventRecord) 
{
        }
 
        metrics.GetEventMetrics().IncEventsCreated()
+
+       ec.RLock()
+       defer ec.RUnlock()
+
+       if ec.isStopped() {
+               metrics.GetEventMetrics().IncEventsNotChanneled()
+               return
+       }
+
        select {
        case ec.channel <- event:
                metrics.GetEventMetrics().IncEventsChanneled()
diff --git a/pkg/events/event_system_test.go b/pkg/events/event_system_test.go
index 7bce1f1f..18b24ae4 100644
--- a/pkg/events/event_system_test.go
+++ b/pkg/events/event_system_test.go
@@ -21,6 +21,7 @@ package events
 import (
        "strconv"
        "strings"
+       "sync"
        "testing"
        "time"
 
@@ -241,3 +242,31 @@ func TestTruncateEventMessage(t *testing.T) {
 func getTestString(stringLength int) string {
        return strings.Repeat("x", stringLength)
 }
+
+// TestAddEventConcurrentStop verifies AddEvent and Stop can run concurrently 
without data races.
+func TestAddEventConcurrentStop(t *testing.T) {
+       Init()
+       eventSystem := GetEventSystem().(*EventSystemImpl) //nolint:errcheck
+       eventSystem.StartServiceWithPublisher(false)
+
+       var wg sync.WaitGroup
+       wg.Add(2)
+
+       go func() {
+               defer wg.Done()
+               for i := 0; i < 10000; i++ {
+                       eventSystem.AddEvent(&si.EventRecord{
+                               Type:    si.EventRecord_REQUEST,
+                               Message: strconv.Itoa(i),
+                       })
+               }
+       }()
+
+       go func() {
+               defer wg.Done()
+               time.Sleep(time.Millisecond)
+               eventSystem.Stop()
+       }()
+
+       wg.Wait()
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to