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