diff options
author | Jamie Liu <jamieliu@google.com> | 2020-08-18 12:30:10 -0700 |
---|---|---|
committer | Rahat Mahmood <46939889+mrahatm@users.noreply.github.com> | 2020-08-19 11:38:34 -0700 |
commit | 596ba8e719eeb13bd8c8645ad3083a1ccc941d97 (patch) | |
tree | 3228f1634baebce2e238203784967f91a2fcbe76 /pkg/p9/server.go | |
parent | 8b5e9dbae85d0877a60112055aa304665d5e39fa (diff) |
Wait for all p9 handlers to complete before server shutdown.
... including those invoked via flipcall.
PiperOrigin-RevId: 327283194
Diffstat (limited to 'pkg/p9/server.go')
-rw-r--r-- | pkg/p9/server.go | 27 |
1 files changed, 11 insertions, 16 deletions
diff --git a/pkg/p9/server.go b/pkg/p9/server.go index 60cf94fa1..b9f15e4ed 100644 --- a/pkg/p9/server.go +++ b/pkg/p9/server.go @@ -87,6 +87,9 @@ type connState struct { // version 0 implies 9P2000.L. version uint32 + // pendingWg counts requests that are still being handled. + pendingWg sync.WaitGroup + // -- below relates to the legacy handler -- // recvOkay indicates that a receive may start. @@ -479,7 +482,9 @@ func (cs *connState) lookupChannel(id uint32) *channel { // handle handles a single message. func (cs *connState) handle(m message) (r message) { + cs.pendingWg.Add(1) defer func() { + cs.pendingWg.Done() if r == nil { // Don't allow a panic to propagate. err := recover() @@ -568,6 +573,11 @@ func (cs *connState) handleRequests() { } func (cs *connState) stop() { + // Wait for completion of all inflight requests. This is mostly so that if + // a request is stuck, the sandbox supervisor has the opportunity to kill + // us with SIGABRT to get a stack dump of the offending handler. + cs.pendingWg.Wait() + // Close all channels. close(cs.recvOkay) close(cs.recvDone) @@ -606,11 +616,6 @@ func (cs *connState) stop() { // service services requests concurrently. func (cs *connState) service() error { - // Pending is the number of handlers that have finished receiving but - // not finished processing requests. These must be waiting on properly - // below. See the next comment for an explanation of the loop. - pending := 0 - // Start the first request handler. go cs.handleRequests() // S/R-SAFE: Irrelevant. cs.recvOkay <- true @@ -622,16 +627,9 @@ func (cs *connState) service() error { select { case err := <-cs.recvDone: if err != nil { - // Wait for pending handlers. - for i := 0; i < pending; i++ { - <-cs.sendDone - } - return nil + return err } - // This handler is now pending. - pending++ - // Kick the next receiver, or start a new handler // if no receiver is currently waiting. select { @@ -642,9 +640,6 @@ func (cs *connState) service() error { } case <-cs.sendDone: - // This handler is finished. - pending-- - // Error sending a response? Nothing can be done. // // We don't terminate on a send error though, since |