soheilhy / cmux

Connection multiplexer for GoLang: serve different services on the same port!
Apache License 2.0
2.59k stars 200 forks source link

Ability to stop cmux listeners #39

Open chandradeepak opened 7 years ago

chandradeepak commented 7 years ago

Feature request: Right now once we start cmux.Serve is there a way to clean shut down the cmux listeners and all its internal listeners it starts. So that way during the whole service shut down we call cmux.Stop and make sure all the listeners are shut down clean.

chandradeepak commented 7 years ago

may be some thing like a Stop method which not only does the m.root.Close() and also make sure it closes other connections .

`defer func() { close(m.donec) wg.Wait()

    for _, sl := range m.sls {
        close(sl.l.connc)
        // Drain the connections enqueued for the listener.
        for c := range sl.l.connc {
            _ = c.Close()
        }
    }
}()`

Most of it is there in defer func of Serve.

so we need to make sure it doesn't happen at two places .

shabbyrobe commented 6 years ago

I don't see a neat way to close cmux down at all. I could be misreading the docs but even though it says ErrListenerClosed is supposed to be returned, I get a net.OpError instead that says "use of closed network connection".

wood-jp commented 6 years ago

Any progress on this? I'm using cmux to share HTTP/REST and gRPC on the same port as I slowly transition from the former to the later. Both of those have graceful shutdown options, but I find that cmux.Serve() does not throw a clear error (I get the same thing as @shabbyrobe), making my life difficult.

puellanivis commented 3 years ago

So, while a “graceful shutdown” is in part available through PR-69 to call a Close() function, the unexported muxListener type that wraps the net.Listener that is the actual net.Listener set during the cmux.New(), does not implement its own Close() function, so when either a gRPC or HTTP server is told to gracefully shutdown, it will passthrough close the main net.Listener port, breaking cmux.CMux.Serve and any other service also setup.

Ideally, the cmux.CMux.Close() would handle closing the actual net.Listener (so new connections are rejected) and then the Close() from each of the muxListener children will only close their own individual acceptance channels, which will then allow all pending Accept to be drained, and then the server shutdown once all the outstanding handlers finish.