diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-06-25 22:47:11 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-06-25 22:47:11 +0000 |
commit | 17e7bcb5b604f278a3280b7e23c4971f3dcd02a4 (patch) | |
tree | 9a107e55f7fae52006886146739b6ae9d4f1c6da | |
parent | 5385b6be1e80d14746766df036a20d55d91a0bb8 (diff) | |
parent | e5526f4f2696a2334d61b05f31ad23b7bee4342b (diff) |
Merge release-20210614.0-34-ge5526f4f2 (automated)
-rw-r--r-- | pkg/control/server/server.go | 5 | ||||
-rw-r--r-- | pkg/urpc/urpc.go | 51 | ||||
-rw-r--r-- | runsc/boot/controller.go | 6 | ||||
-rw-r--r-- | runsc/sandbox/sandbox.go | 6 |
4 files changed, 48 insertions, 20 deletions
diff --git a/pkg/control/server/server.go b/pkg/control/server/server.go index 629dae8f4..889568177 100644 --- a/pkg/control/server/server.go +++ b/pkg/control/server/server.go @@ -22,6 +22,7 @@ package server import ( "os" + "time" "gvisor.dev/gvisor/pkg/log" "gvisor.dev/gvisor/pkg/sync" @@ -65,13 +66,13 @@ func (s *Server) Wait() { // Stop stops the server. Note that this function should only be called once // and the server should not be used afterwards. -func (s *Server) Stop() { +func (s *Server) Stop(timeout time.Duration) { s.socket.Close() s.Wait() // This will cause existing clients to be terminated safely. If the // registered handlers have a Stop callback, it will be called. - s.server.Stop() + s.server.Stop(timeout) } // StartServing starts listening for connect and spawns the main service diff --git a/pkg/urpc/urpc.go b/pkg/urpc/urpc.go index 0e9a829f6..0ef635a2f 100644 --- a/pkg/urpc/urpc.go +++ b/pkg/urpc/urpc.go @@ -27,6 +27,7 @@ import ( "os" "reflect" "runtime" + "time" "gvisor.dev/gvisor/pkg/fd" "gvisor.dev/gvisor/pkg/log" @@ -458,29 +459,45 @@ func (s *Server) StartHandling(client *unet.Socket) { // No new requests should be initiated after calling Stop. Existing clients // will be closed after completing any pending RPCs. This method will block // until all clients have disconnected. -func (s *Server) Stop() { - // Wait for all outstanding requests. - defer s.wg.Wait() - +// +// timeout is the time for clients to complete ongoing RPCs. +func (s *Server) Stop(timeout time.Duration) { // Call any Stop callbacks. for _, stopper := range s.stoppers { stopper.Stop() } - // Close all known clients. - s.mu.Lock() - defer s.mu.Unlock() - for client, state := range s.clients { - switch state { - case idle: - // Close connection now. - client.Close() - s.clients[client] = closed - case processing: - // Request close when done. - s.clients[client] = closeRequested + done := make(chan bool, 1) + go func() { + if timeout != 0 { + timer := time.NewTicker(timeout) + defer timer.Stop() + select { + case <-done: + return + case <-timer.C: + } } - } + + // Close all known clients. + s.mu.Lock() + defer s.mu.Unlock() + for client, state := range s.clients { + switch state { + case idle: + // Close connection now. + client.Close() + s.clients[client] = closed + case processing: + // Request close when done. + s.clients[client] = closeRequested + } + } + }() + + // Wait for all outstanding requests. + s.wg.Wait() + done <- true } // Client is a urpc client. diff --git a/runsc/boot/controller.go b/runsc/boot/controller.go index d52cf5a00..34f939953 100644 --- a/runsc/boot/controller.go +++ b/runsc/boot/controller.go @@ -18,6 +18,7 @@ import ( "errors" "fmt" "os" + gtime "time" specs "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/sys/unix" @@ -165,8 +166,11 @@ func newController(fd int, l *Loader) (*controller, error) { return ctrl, nil } +// stopRPCTimeout is the time for clients to complete ongoing RPCs. +const stopRPCTimeout = 15 * gtime.Second + func (c *controller) stop() { - c.srv.Stop() + c.srv.Stop(stopRPCTimeout) } // containerManager manages sandbox containers. diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go index 29e202b7d..f14cc7229 100644 --- a/runsc/sandbox/sandbox.go +++ b/runsc/sandbox/sandbox.go @@ -797,7 +797,13 @@ func (s *Sandbox) Wait(cid string) (unix.WaitStatus, error) { // Try the Wait RPC to the sandbox. var ws unix.WaitStatus err = conn.Call(boot.ContainerWait, &cid, &ws) + conn.Close() if err == nil { + if s.IsRootContainer(cid) { + if err := s.waitForStopped(); err != nil { + return unix.WaitStatus(0), err + } + } // It worked! return ws, nil } |