mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-07-23 07:43:29 +03:00
67 lines
1.3 KiB
Go
67 lines
1.3 KiB
Go
package interrupt
|
|
|
|
import (
|
|
"net"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
type closeBarrierConn struct {
|
|
net.Conn
|
|
barrier *sync.WaitGroup
|
|
}
|
|
|
|
func (c *closeBarrierConn) Close() error {
|
|
c.barrier.Done()
|
|
c.barrier.Wait()
|
|
return c.Conn.Close()
|
|
}
|
|
|
|
func TestNestedGroupsInterruptWithoutDeadlock(t *testing.T) {
|
|
groupA := NewGroup()
|
|
groupB := NewGroup()
|
|
barrier := &sync.WaitGroup{}
|
|
barrier.Add(2)
|
|
|
|
barrierA, barrierAPeer := net.Pipe()
|
|
barrierB, barrierBPeer := net.Pipe()
|
|
t.Cleanup(func() {
|
|
barrierAPeer.Close()
|
|
barrierBPeer.Close()
|
|
})
|
|
groupA.NewConn(&closeBarrierConn{Conn: barrierA, barrier: barrier}, true, false)
|
|
groupB.NewConn(&closeBarrierConn{Conn: barrierB, barrier: barrier}, true, false)
|
|
|
|
connA, connAPeer := net.Pipe()
|
|
connB, connBPeer := net.Pipe()
|
|
t.Cleanup(func() {
|
|
connAPeer.Close()
|
|
connBPeer.Close()
|
|
})
|
|
wrapperA := groupA.NewConn(connA, true, false)
|
|
wrapperB := groupB.NewConn(connB, true, false)
|
|
groupA.NewConn(wrapperB, true, false)
|
|
groupB.NewConn(wrapperA, true, false)
|
|
|
|
done := make(chan struct{}, 2)
|
|
go func() {
|
|
groupA.Interrupt(true)
|
|
done <- struct{}{}
|
|
}()
|
|
go func() {
|
|
groupB.Interrupt(true)
|
|
done <- struct{}{}
|
|
}()
|
|
|
|
timeout := time.NewTimer(time.Second)
|
|
defer timeout.Stop()
|
|
for range 2 {
|
|
select {
|
|
case <-done:
|
|
case <-timeout.C:
|
|
t.Fatal("nested group interrupt deadlocked")
|
|
}
|
|
}
|
|
}
|