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