waithelper.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. //go:build windows
  2. package hcs
  3. import (
  4. "context"
  5. "time"
  6. "github.com/Microsoft/hcsshim/internal/log"
  7. )
  8. func processAsyncHcsResult(
  9. ctx context.Context,
  10. err error,
  11. resultJSON string,
  12. callbackNumber uintptr,
  13. expectedNotification hcsNotification,
  14. timeout *time.Duration,
  15. ) ([]ErrorEvent, error) {
  16. events := processHcsResult(ctx, resultJSON)
  17. if IsPending(err) {
  18. return nil, waitForNotification(ctx, callbackNumber, expectedNotification, timeout)
  19. }
  20. return events, err
  21. }
  22. func waitForNotification(
  23. ctx context.Context,
  24. callbackNumber uintptr,
  25. expectedNotification hcsNotification,
  26. timeout *time.Duration,
  27. ) error {
  28. callbackMapLock.RLock()
  29. if _, ok := callbackMap[callbackNumber]; !ok {
  30. callbackMapLock.RUnlock()
  31. log.G(ctx).WithField("callbackNumber", callbackNumber).Error("failed to waitForNotification: callbackNumber does not exist in callbackMap")
  32. return ErrHandleClose
  33. }
  34. channels := callbackMap[callbackNumber].channels
  35. callbackMapLock.RUnlock()
  36. expectedChannel := channels[expectedNotification]
  37. if expectedChannel == nil {
  38. log.G(ctx).WithField("type", expectedNotification).Error("unknown notification type in waitForNotification")
  39. return ErrInvalidNotificationType
  40. }
  41. var c <-chan time.Time
  42. if timeout != nil {
  43. timer := time.NewTimer(*timeout)
  44. c = timer.C
  45. defer timer.Stop()
  46. }
  47. select {
  48. case err, ok := <-expectedChannel:
  49. if !ok {
  50. return ErrHandleClose
  51. }
  52. return err
  53. case err, ok := <-channels[hcsNotificationSystemExited]:
  54. if !ok {
  55. return ErrHandleClose
  56. }
  57. // If the expected notification is hcsNotificationSystemExited which of the two selects
  58. // chosen is random. Return the raw error if hcsNotificationSystemExited is expected
  59. if channels[hcsNotificationSystemExited] == expectedChannel {
  60. return err
  61. }
  62. return ErrUnexpectedContainerExit
  63. case _, ok := <-channels[hcsNotificationServiceDisconnect]:
  64. if !ok {
  65. return ErrHandleClose
  66. }
  67. // hcsNotificationServiceDisconnect should never be an expected notification
  68. // it does not need the same handling as hcsNotificationSystemExited
  69. return ErrUnexpectedProcessAbort
  70. case <-c:
  71. return ErrTimeout
  72. }
  73. }