diff --git a/state_impl.go b/state_impl.go index 2ad1ae6..5688603 100644 --- a/state_impl.go +++ b/state_impl.go @@ -244,6 +244,7 @@ func (p *Proxy) Stop() { for _, server := range p.servers { server.Stop() } + p.closeAllMiners() if p.watcher != nil { p.watcher.Stop() } @@ -262,6 +263,23 @@ func (p *Proxy) Stop() { }) } +func (p *Proxy) closeAllMiners() { + if p == nil { + return + } + p.minersMu.RLock() + miners := make([]*Miner, 0, len(p.miners)) + for _, miner := range p.miners { + miners = append(miners, miner) + } + p.minersMu.RUnlock() + for _, miner := range miners { + if miner != nil { + miner.Close() + } + } +} + // Reload swaps the live configuration and updates dependent state. func (p *Proxy) Reload(cfg *Config) { if p == nil || cfg == nil { diff --git a/state_stop_test.go b/state_stop_test.go new file mode 100644 index 0000000..111ac73 --- /dev/null +++ b/state_stop_test.go @@ -0,0 +1,62 @@ +package proxy + +import ( + "net" + "testing" + "time" +) + +func TestProxy_Stop_Good(t *testing.T) { + serverConn, clientConn := net.Pipe() + defer serverConn.Close() + + miner := NewMiner(clientConn, 3333, nil) + proxyInstance := &Proxy{ + done: make(chan struct{}), + miners: map[int64]*Miner{miner.ID(): miner}, + } + + done := make(chan error, 1) + go func() { + buf := make([]byte, 1) + _, err := serverConn.Read(buf) + done <- err + }() + + time.Sleep(10 * time.Millisecond) + proxyInstance.Stop() + + select { + case err := <-done: + if err == nil { + t.Fatalf("expected miner connection to close during Stop") + } + case <-time.After(time.Second): + t.Fatalf("expected miner connection to close during Stop") + } +} + +func TestProxy_Stop_Bad(t *testing.T) { + var proxyInstance *Proxy + + proxyInstance.Stop() +} + +func TestProxy_Stop_Ugly(t *testing.T) { + serverConn, clientConn := net.Pipe() + defer serverConn.Close() + + miner := NewMiner(clientConn, 3333, nil) + proxyInstance := &Proxy{ + done: make(chan struct{}), + miners: map[int64]*Miner{miner.ID(): miner}, + } + + proxyInstance.Stop() + proxyInstance.Stop() + + buf := make([]byte, 1) + if _, err := serverConn.Read(buf); err == nil { + t.Fatalf("expected closed connection after repeated Stop calls") + } +}