watcher.go 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. package hcs
  2. import (
  3. "context"
  4. "github.com/Microsoft/hcsshim/internal/logfields"
  5. "github.com/Microsoft/hcsshim/internal/timeout"
  6. "github.com/sirupsen/logrus"
  7. )
  8. // syscallWatcher is used as a very simple goroutine around calls into
  9. // the platform. In some cases, we have seen HCS APIs not returning due to
  10. // various bugs, and the goroutine making the syscall ends up not returning,
  11. // prior to its async callback. By spinning up a syscallWatcher, it allows
  12. // us to at least log a warning if a syscall doesn't complete in a reasonable
  13. // amount of time.
  14. //
  15. // Usage is:
  16. //
  17. // syscallWatcher(logContext, func() {
  18. // err = <syscall>(args...)
  19. // })
  20. //
  21. func syscallWatcher(logContext logrus.Fields, syscallLambda func()) {
  22. ctx, cancel := context.WithTimeout(context.Background(), timeout.SyscallWatcher)
  23. defer cancel()
  24. go watchFunc(ctx, logContext)
  25. syscallLambda()
  26. }
  27. func watchFunc(ctx context.Context, logContext logrus.Fields) {
  28. select {
  29. case <-ctx.Done():
  30. if ctx.Err() != context.Canceled {
  31. logrus.WithFields(logContext).
  32. WithField(logfields.Timeout, timeout.SyscallWatcher).
  33. Warning("Syscall did not complete within operation timeout. This may indicate a platform issue. If it appears to be making no forward progress, obtain the stacks and see if there is a syscall stuck in the platform API for a significant length of time.")
  34. }
  35. }
  36. }