Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pkg/daemon/ipc.go
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,9 @@ func (s *IPCServer) handleBind(conn *ipcConn, reqID uint64, payload []byte) {

// Start pushing accepted connections to this client. CmdAccept frames
// are server-pushed (reqID=0) and demuxed by the driver on local port.
s.daemon.bgWG.Add(1)
go func() {
defer s.daemon.bgWG.Done()
for c := range ln.AcceptCh {
conn.trackConn(c.ID)
// H12 fix: include local port for per-port demux
Expand Down
2 changes: 2 additions & 0 deletions pkg/daemon/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ func (d *Daemon) startEchoService() error {
if err != nil {
return err
}
d.bgWG.Add(1)
go func() {
defer d.bgWG.Done()
for {
select {
case conn, ok := <-ln.AcceptCh:
Expand Down
33 changes: 33 additions & 0 deletions pkg/daemon/zz_services_bootstrap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,36 @@ func TestStartEchoServiceAcceptLoopExitsOnUnbind(t *testing.T) {
// detached goroutine but Sleep gives it a chance to drain.
time.Sleep(100 * time.Millisecond)
}

// --- startEchoService increments bgWG and stopCh drains it ---

func TestStartEchoServiceBGWaitGroupTracksAcceptLoop(t *testing.T) {
t.Parallel()
d := New(Config{})

if err := d.startEchoService(); err != nil {
t.Fatalf("startEchoService: %v", err)
}

// Close stopCh — accept loop should exit via <-d.stopCh and
// defer d.bgWG.Done() fires, draining the WaitGroup.
close(d.stopCh)

if !wgDrained(&d.bgWG, 2*time.Second) {
t.Fatal("bgWG not drained within 2s after stopCh close")
}
}

func wgDrained(wg *sync.WaitGroup, timeout time.Duration) bool {
ch := make(chan struct{})
go func() {
wg.Wait()
close(ch)
}()
select {
case <-ch:
return true
case <-time.After(timeout):
return false
}
}
Loading