waithelper.go 1.9 KB

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