code: func (m *Manager) stop(cleaner func(Proxy) error) error {
  	for {
  		// Special case state that exits the for loop
  		if m.runState == managerStateStopped {
  			break
  		}
  
  		switch m.runState {
  		case managerStateIdle:
  			// Idle so just set it to stopped and return. We notify
  			// the condition variable in case others are waiting.
  			m.runState = managerStateStopped
  			m.cond.Broadcast()
  			return nil
  
  		case managerStateRunning:
  			// Set the state to stopping and broadcast to all waiters,
  			// since Run is sitting on cond.Wait.
  			m.runState = managerStateStopping
  			m.cond.Broadcast()
  			m.cond.Wait() // Wait on the stopping event
  
  		case managerStateStopping:
  			// Still stopping, wait...
  			m.cond.Wait()
  		}
  	}
  
  	// Clean up all the proxies
  	var err error
  	for id, proxy := range m.proxies {
  		if err := cleaner(proxy); err != nil {
  			err = multierror.Append(
  				err, fmt.Errorf("failed to stop proxy %q: %s", id, err))
  			continue
  		}
  
  		// Remove it since it is already stopped successfully
  		delete(m.proxies, id)
  	}
  
  	return err
  }
docs: // stop stops the run loop and cleans up all the proxies by calling
  // the given cleaner. If the cleaner returns an error the proxy won't be
  // removed from the map.
  //
  // The lock must be held while this is called.