func (b *Box) waitLoop(ctx context.Context) { apexctx.GetLogger(ctx).Info("start waitLoop") var ( portoConn porto.API err error ) waitPattern := filepath.Join(b.rootPrefix, "*") var waitTimeout = 30 * time.Second closed := func(portoConn porto.API) bool { select { case <-ctx.Done(): if portoConn != nil { portoConn.Close() } return true default: return false } } LOOP: for { apexctx.GetLogger(ctx).Info("next iteration of waitLoop") if closed(portoConn) { return } // Connect to Porto if we have not connected yet. // In case of error: wait either a fixed timeout or closing of Box if portoConn == nil { apexctx.GetLogger(ctx).Info("waitLoop: connect to Portod") portoConn, err = portoConnect() if err != nil { apexctx.GetLogger(ctx).WithError(err).Warn("unable to connect to Portod") select { case <-time.After(time.Second): continue LOOP case <-ctx.Done(): return } } } // * means all containers // if no containers dead for waitTimeout, name will be an empty string containerName, err := portoConn.Wait([]string{waitPattern}, 30*waitTimeout) if err != nil { portoConn.Close() portoConn = nil continue LOOP } if containerName != "" { apexctx.GetLogger(ctx).Infof("Wait reports %s to be dead", containerName) b.muContainers.Lock() container, ok := b.containers[containerName] if ok { delete(b.containers, containerName) } rest := len(b.containers) b.muContainers.Unlock() if ok { if err = container.Kill(); err != nil { apexctx.GetLogger(ctx).WithError(err).Errorf("Killing %s error", containerName) } } apexctx.GetLogger(ctx).Infof("%d containers are being tracked now", rest) } } }