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