// Shutdown shuts down the proxy gracefully. It firsts closes the active
// listeners, then it sets read and write deadlines on all the active
// connections, this is the hard limit for all the communications to complete.
//
// If shutdown is successful then nil error is returned. Otherwise a non-nil
// error provides the reason.
//
// If proxy is not running then ErrNotRunning is returned immediately.
//
// If proxy is already in shutdown mode then ErrShuttingDown is returned
// immediately.
Shutdown shuts down the proxy gracefully. It firsts closes the active
listeners, then it sets read and write deadlines on all the active
connections, this is the hard limit for all the communications to complete.

If shutdown is successful then nil error is returned. Otherwise a non-nil
error provides the reason.

If proxy is not running then ErrNotRunning is returned immediately.

If proxy is already in shutdown mode then ErrShuttingDown is returned
immediately.
// Shutdown shuts down the proxy gracefully . It firsts closes the active // listeners then it sets read and write deadlines on all the active // connections this is the hard limit for all the communications to complete . // // If shutdown is successful then nil error is returned . Otherwise a non - nil // error provides the reason . // // If proxy is not running then ErrNotRunning is returned immediately . // // If proxy is already in shutdown mode then ErrShuttingDown is returned // immediately .
func (p *Proxy) Shutdown(ctx context.Context) error {
	if !p.isRunning() {
		return ErrNotRunning
	}
	if !atomic.CompareAndSwapInt32(&p.inShutdown, 0, 1) {
		return ErrShuttingDown
	}
	defer atomic.StoreInt32(&p.inShutdown, 0)
	var err error
	p.mu.Lock()
	for ln := range p.listeners {
		if cerr := (*ln).Close(); cerr != nil && err == nil {
			err = cerr
		}
	}
	p.done()
	p.mu.Unlock()
	for {
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-time.After(200 * time.Millisecond):
			p.mu.Lock()
			if len(p.activeConns) == 0 {
				p.mu.Unlock()
				return err
			}
			p.mu.Unlock()
		}
	}
}
func ( p * Proxy ) Shutdown ( ctx context . Context ) error { if ! p . isRunning ( ) { return ErrNotRunning } if ! atomic . CompareAndSwapInt32 ( & p . inShutdown , 0 , 1 ) { return ErrShuttingDown } defer atomic . StoreInt32 ( & p . inShutdown , 0 ) var err error p . mu . Lock ( ) for ln := range p . listeners { if cerr := ( * ln ) . Close ( ) ; cerr != nil && err == nil { err = cerr } } p . done ( ) p . mu . Unlock ( ) for { select { case <- ctx . Done ( ) : return ctx . Err ( ) case <- time . After ( 200 * time . Millisecond ) : p . mu . Lock ( ) if len ( p . activeConns ) == 0 { p . mu . Unlock ( ) return err } p . mu . Unlock ( ) } } }
Shutdown shuts down the proxy gracefully.
Shutdown shuts down the proxy gracefully .