(ctx context.Context, sandboxID string)
| 136 | } |
| 137 | |
| 138 | func (s *remoteSandboxController) Wait(ctx context.Context, sandboxID string) (sandbox.ExitStatus, error) { |
| 139 | // For remote sandbox controllers, the controller process may restart, |
| 140 | // we have to retry if the error indicates that it is the grpc disconnection. |
| 141 | var ( |
| 142 | resp *api.ControllerWaitResponse |
| 143 | err error |
| 144 | retryInterval time.Duration = 128 |
| 145 | ) |
| 146 | for { |
| 147 | resp, err = s.client.Wait(ctx, &api.ControllerWaitRequest{ |
| 148 | SandboxID: sandboxID, |
| 149 | Sandboxer: s.sandboxerName, |
| 150 | }) |
| 151 | if err != nil { |
| 152 | grpcErr := errgrpc.ToNative(err) |
| 153 | if !errdefs.IsUnavailable(grpcErr) { |
| 154 | return sandbox.ExitStatus{}, grpcErr |
| 155 | } |
| 156 | select { |
| 157 | case <-time.After(retryInterval * time.Millisecond): |
| 158 | if retryInterval < 4096 { |
| 159 | retryInterval = retryInterval << 1 |
| 160 | } |
| 161 | continue |
| 162 | case <-ctx.Done(): |
| 163 | return sandbox.ExitStatus{}, grpcErr |
| 164 | } |
| 165 | } |
| 166 | break |
| 167 | } |
| 168 | |
| 169 | return sandbox.ExitStatus{ |
| 170 | ExitStatus: resp.GetExitStatus(), |
| 171 | ExitedAt: resp.GetExitedAt().AsTime(), |
| 172 | }, nil |
| 173 | } |
| 174 | |
| 175 | func (s *remoteSandboxController) Status(ctx context.Context, sandboxID string, verbose bool) (sandbox.ControllerStatus, error) { |
| 176 | resp, err := s.client.Status(ctx, &api.ControllerStatusRequest{ |
nothing calls this directly
no test coverage detected