diff options
author | Cecylia Bocovich <cohosh@torproject.org> | 2020-10-29 16:21:37 -0400 |
---|---|---|
committer | Cecylia Bocovich <cohosh@torproject.org> | 2020-12-05 15:50:16 -0500 |
commit | b9cc54b3b7dbd76d85613f0f478c95b193441564 (patch) | |
tree | 2b1498bc4b61eaa05bb25eba8e6c29426fbfd382 | |
parent | 114df695ceff25d0213200a3368ed7a1bb1c7668 (diff) | |
download | snowflake-b9cc54b3b7dbd76d85613f0f478c95b193441564.tar.gz snowflake-b9cc54b3b7dbd76d85613f0f478c95b193441564.zip |
Send shutdown signal to shutdown open connections
Normally all dangling goroutines are terminated when the main function
exits. However, for projects that use a patched version of snowflake as
a library, these goroutines continued running as long as the main function
had not yet terminated. This commit has all open SOCKS connections close
after receiving a shutdown signal.
-rw-r--r-- | client/snowflake.go | 25 |
1 files changed, 20 insertions, 5 deletions
diff --git a/client/snowflake.go b/client/snowflake.go index a1b97fa..a1a679e 100644 --- a/client/snowflake.go +++ b/client/snowflake.go @@ -27,7 +27,7 @@ const ( ) // Accept local SOCKS connections and pass them to the handler. -func socksAcceptLoop(ln *pt.SocksListener, tongue sf.Tongue) { +func socksAcceptLoop(ln *pt.SocksListener, tongue sf.Tongue, shutdown chan struct{}) { defer ln.Close() for { conn, err := ln.AcceptSocks() @@ -48,11 +48,23 @@ func socksAcceptLoop(ln *pt.SocksListener, tongue sf.Tongue) { return } - err = sf.Handler(conn, tongue) - if err != nil { - log.Printf("handler error: %s", err) + handler := make(chan struct{}) + go func() { + err = sf.Handler(conn, tongue) + if err != nil { + log.Printf("handler error: %s", err) + } + close(handler) return + + }() + select { + case <-shutdown: + log.Println("Received shutdown signal") + case <-handler: + log.Println("Handler ended") } + return }() } } @@ -160,6 +172,7 @@ func main() { os.Exit(1) } listeners := make([]net.Listener, 0) + shutdown := make(chan struct{}) for _, methodName := range ptInfo.MethodNames { switch methodName { case "snowflake": @@ -170,7 +183,7 @@ func main() { break } log.Printf("Started SOCKS listener at %v.", ln.Addr()) - go socksAcceptLoop(ln, dialer) + go socksAcceptLoop(ln, dialer, shutdown) pt.Cmethod(methodName, ln.Version(), ln.Addr()) listeners = append(listeners, ln) default: @@ -196,11 +209,13 @@ func main() { // Wait for a signal. <-sigChan + log.Println("stopping snowflake") // Signal received, shut down. for _, ln := range listeners { ln.Close() } + close(shutdown) log.Println("snowflake is done.") } |