Signed-off-by: Darren Stahl <darst@microsoft.com>
Darren Stahl authored on 2016/06/01 04:51:29... | ... |
@@ -43,7 +43,7 @@ esac |
43 | 43 |
|
44 | 44 |
# the following lines are in sorted order, FYI |
45 | 45 |
clone git github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62 |
46 |
-clone git github.com/Microsoft/hcsshim v0.3.0 |
|
46 |
+clone git github.com/Microsoft/hcsshim v0.3.1 |
|
47 | 47 |
clone git github.com/Microsoft/go-winio v0.3.4 |
48 | 48 |
clone git github.com/Sirupsen/logrus v0.10.0 # logrus is a common dependency among multiple deps |
49 | 49 |
clone git github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a |
... | ... |
@@ -6740,3 +6740,18 @@ func (s *DockerSuite) TestBuildLabelsOverride(c *check.C) { |
6740 | 6740 |
} |
6741 | 6741 |
|
6742 | 6742 |
} |
6743 |
+ |
|
6744 |
+// Test case for #22855 |
|
6745 |
+func (s *DockerSuite) TestBuildDeleteCommittedFile(c *check.C) { |
|
6746 |
+ name := "test-delete-committed-file" |
|
6747 |
+ |
|
6748 |
+ _, err := buildImage(name, |
|
6749 |
+ `FROM busybox |
|
6750 |
+ RUN echo test > file |
|
6751 |
+ RUN test -e file |
|
6752 |
+ RUN rm file |
|
6753 |
+ RUN sh -c "! test -e file"`, false) |
|
6754 |
+ if err != nil { |
|
6755 |
+ c.Fatal(err) |
|
6756 |
+ } |
|
6757 |
+} |
... | ... |
@@ -40,39 +40,36 @@ type hcsNotification uint32 |
40 | 40 |
type notificationChannel chan error |
41 | 41 |
|
42 | 42 |
type notifcationWatcherContext struct { |
43 |
- channel notificationChannel |
|
44 |
- expectedNotification hcsNotification |
|
45 |
- handle hcsCallback |
|
43 |
+ channels notificationChannels |
|
44 |
+ handle hcsCallback |
|
45 |
+} |
|
46 |
+ |
|
47 |
+type notificationChannels map[hcsNotification]notificationChannel |
|
48 |
+ |
|
49 |
+func newChannels() notificationChannels { |
|
50 |
+ channels := make(notificationChannels) |
|
51 |
+ |
|
52 |
+ channels[hcsNotificationSystemExited] = make(notificationChannel, 1) |
|
53 |
+ channels[hcsNotificationSystemCreateCompleted] = make(notificationChannel, 1) |
|
54 |
+ channels[hcsNotificationSystemStartCompleted] = make(notificationChannel, 1) |
|
55 |
+ channels[hcsNotificationSystemPauseCompleted] = make(notificationChannel, 1) |
|
56 |
+ channels[hcsNotificationSystemResumeCompleted] = make(notificationChannel, 1) |
|
57 |
+ channels[hcsNotificationProcessExited] = make(notificationChannel, 1) |
|
58 |
+ channels[hcsNotificationServiceDisconnect] = make(notificationChannel, 1) |
|
59 |
+ return channels |
|
46 | 60 |
} |
47 | 61 |
|
48 | 62 |
func notificationWatcher(notificationType hcsNotification, callbackNumber uintptr, notificationStatus uintptr, notificationData *uint16) uintptr { |
49 |
- var ( |
|
50 |
- result error |
|
51 |
- completeWait = false |
|
52 |
- ) |
|
63 |
+ var result error |
|
64 |
+ if int32(notificationStatus) < 0 { |
|
65 |
+ result = syscall.Errno(win32FromHresult(notificationStatus)) |
|
66 |
+ } |
|
53 | 67 |
|
54 | 68 |
callbackMapLock.RLock() |
55 |
- context := callbackMap[callbackNumber] |
|
69 |
+ channels := callbackMap[callbackNumber].channels |
|
56 | 70 |
callbackMapLock.RUnlock() |
57 | 71 |
|
58 |
- if notificationType == context.expectedNotification { |
|
59 |
- if int32(notificationStatus) < 0 { |
|
60 |
- result = syscall.Errno(win32FromHresult(notificationStatus)) |
|
61 |
- } else { |
|
62 |
- result = nil |
|
63 |
- } |
|
64 |
- completeWait = true |
|
65 |
- } else if notificationType == hcsNotificationSystemExited { |
|
66 |
- result = ErrUnexpectedContainerExit |
|
67 |
- completeWait = true |
|
68 |
- } else if notificationType == hcsNotificationServiceDisconnect { |
|
69 |
- result = ErrUnexpectedProcessAbort |
|
70 |
- completeWait = true |
|
71 |
- } |
|
72 |
- |
|
73 |
- if completeWait { |
|
74 |
- context.channel <- result |
|
75 |
- } |
|
72 |
+ channels[notificationType] <- result |
|
76 | 73 |
|
77 | 74 |
return 0 |
78 | 75 |
} |
... | ... |
@@ -26,8 +26,9 @@ type ContainerError struct { |
26 | 26 |
} |
27 | 27 |
|
28 | 28 |
type container struct { |
29 |
- handle hcsSystem |
|
30 |
- id string |
|
29 |
+ handle hcsSystem |
|
30 |
+ id string |
|
31 |
+ callbackNumber uintptr |
|
31 | 32 |
} |
32 | 33 |
|
33 | 34 |
type containerProperties struct { |
... | ... |
@@ -47,7 +48,6 @@ type containerProperties struct { |
47 | 47 |
func CreateContainer(id string, c *ContainerConfig) (Container, error) { |
48 | 48 |
operation := "CreateContainer" |
49 | 49 |
title := "HCSShim::" + operation |
50 |
- logrus.Debugf(title+" id=%s", id) |
|
51 | 50 |
|
52 | 51 |
container := &container{ |
53 | 52 |
id: id, |
... | ... |
@@ -59,21 +59,28 @@ func CreateContainer(id string, c *ContainerConfig) (Container, error) { |
59 | 59 |
} |
60 | 60 |
|
61 | 61 |
configuration := string(configurationb) |
62 |
+ logrus.Debugf(title+" id=%s config=%s", id, configuration) |
|
62 | 63 |
|
63 | 64 |
var ( |
64 |
- handle hcsSystem |
|
65 | 65 |
resultp *uint16 |
66 | 66 |
createError error |
67 | 67 |
) |
68 | 68 |
if hcsCallbacksSupported { |
69 | 69 |
var identity syscall.Handle |
70 |
- createError = hcsCreateComputeSystem(id, configuration, identity, &handle, &resultp) |
|
70 |
+ createError = hcsCreateComputeSystem(id, configuration, identity, &container.handle, &resultp) |
|
71 |
+ |
|
72 |
+ if createError == nil || createError == ErrVmcomputeOperationPending { |
|
73 |
+ if err := container.registerCallback(); err != nil { |
|
74 |
+ err := &ContainerError{Container: container, Operation: operation, Err: err} |
|
75 |
+ logrus.Error(err) |
|
76 |
+ return nil, err |
|
77 |
+ } |
|
78 |
+ } |
|
71 | 79 |
} else { |
72 |
- createError = hcsCreateComputeSystemTP5(id, configuration, &handle, &resultp) |
|
80 |
+ createError = hcsCreateComputeSystemTP5(id, configuration, &container.handle, &resultp) |
|
73 | 81 |
} |
74 |
- container.handle = handle |
|
75 | 82 |
|
76 |
- err = processAsyncHcsResult(container, createError, resultp, hcsNotificationSystemCreateCompleted, &defaultTimeout) |
|
83 |
+ err = processAsyncHcsResult(createError, resultp, container.callbackNumber, hcsNotificationSystemCreateCompleted, &defaultTimeout) |
|
77 | 84 |
if err != nil { |
78 | 85 |
err := &ContainerError{Container: container, Operation: operation, ExtraInfo: configuration, Err: err} |
79 | 86 |
logrus.Error(err) |
... | ... |
@@ -122,7 +129,7 @@ func (container *container) Start() error { |
122 | 122 |
|
123 | 123 |
var resultp *uint16 |
124 | 124 |
err := hcsStartComputeSystemTP5(container.handle, nil, &resultp) |
125 |
- err = processAsyncHcsResult(container, err, resultp, hcsNotificationSystemStartCompleted, &defaultTimeout) |
|
125 |
+ err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemStartCompleted, &defaultTimeout) |
|
126 | 126 |
if err != nil { |
127 | 127 |
err := &ContainerError{Container: container, Operation: operation, Err: err} |
128 | 128 |
logrus.Error(err) |
... | ... |
@@ -186,7 +193,7 @@ func (container *container) Wait() error { |
186 | 186 |
logrus.Debugf(title+" id=%s", container.id) |
187 | 187 |
|
188 | 188 |
if hcsCallbacksSupported { |
189 |
- err := registerAndWaitForCallback(container, hcsNotificationSystemExited) |
|
189 |
+ err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, nil) |
|
190 | 190 |
if err != nil { |
191 | 191 |
err := &ContainerError{Container: container, Operation: operation, Err: err} |
192 | 192 |
logrus.Error(err) |
... | ... |
@@ -217,7 +224,7 @@ func (container *container) WaitTimeout(timeout time.Duration) error { |
217 | 217 |
logrus.Debugf(title+" id=%s", container.id) |
218 | 218 |
|
219 | 219 |
if hcsCallbacksSupported { |
220 |
- err := registerAndWaitForCallbackTimeout(container, hcsNotificationSystemExited, timeout) |
|
220 |
+ err := waitForNotification(container.callbackNumber, hcsNotificationSystemExited, &timeout) |
|
221 | 221 |
if err == ErrTimeout { |
222 | 222 |
return ErrTimeout |
223 | 223 |
} else if err != nil { |
... | ... |
@@ -304,7 +311,7 @@ func (container *container) Pause() error { |
304 | 304 |
|
305 | 305 |
var resultp *uint16 |
306 | 306 |
err := hcsPauseComputeSystemTP5(container.handle, nil, &resultp) |
307 |
- err = processAsyncHcsResult(container, err, resultp, hcsNotificationSystemPauseCompleted, &defaultTimeout) |
|
307 |
+ err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemPauseCompleted, &defaultTimeout) |
|
308 | 308 |
if err != nil { |
309 | 309 |
err := &ContainerError{Container: container, Operation: operation, Err: err} |
310 | 310 |
logrus.Error(err) |
... | ... |
@@ -325,7 +332,7 @@ func (container *container) Resume() error { |
325 | 325 |
) |
326 | 326 |
|
327 | 327 |
err := hcsResumeComputeSystemTP5(container.handle, nil, &resultp) |
328 |
- err = processAsyncHcsResult(container, err, resultp, hcsNotificationSystemResumeCompleted, &defaultTimeout) |
|
328 |
+ err = processAsyncHcsResult(err, resultp, container.callbackNumber, hcsNotificationSystemResumeCompleted, &defaultTimeout) |
|
329 | 329 |
if err != nil { |
330 | 330 |
err := &ContainerError{Container: container, Operation: operation, Err: err} |
331 | 331 |
logrus.Error(err) |
... | ... |
@@ -340,7 +347,6 @@ func (container *container) Resume() error { |
340 | 340 |
func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { |
341 | 341 |
operation := "CreateProcess" |
342 | 342 |
title := "HCSShim::Container::" + operation |
343 |
- logrus.Debugf(title+" id=%s", container.id) |
|
344 | 343 |
var ( |
345 | 344 |
processInfo hcsProcessInformation |
346 | 345 |
processHandle hcsProcess |
... | ... |
@@ -359,6 +365,7 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { |
359 | 359 |
} |
360 | 360 |
|
361 | 361 |
configuration := string(configurationb) |
362 |
+ logrus.Debugf(title+" id=%s config=%s", container.id, configuration) |
|
362 | 363 |
|
363 | 364 |
err = hcsCreateProcess(container.handle, configuration, &processInfo, &processHandle, &resultp) |
364 | 365 |
err = processHcsResult(err, resultp) |
... | ... |
@@ -379,6 +386,14 @@ func (container *container) CreateProcess(c *ProcessConfig) (Process, error) { |
379 | 379 |
}, |
380 | 380 |
} |
381 | 381 |
|
382 |
+ if hcsCallbacksSupported { |
|
383 |
+ if err := process.registerCallback(); err != nil { |
|
384 |
+ err = &ContainerError{Container: container, Operation: operation, Err: err} |
|
385 |
+ logrus.Error(err) |
|
386 |
+ return nil, err |
|
387 |
+ } |
|
388 |
+ } |
|
389 |
+ |
|
382 | 390 |
logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID) |
383 | 391 |
runtime.SetFinalizer(process, closeProcess) |
384 | 392 |
return process, nil |
... | ... |
@@ -408,6 +423,12 @@ func (container *container) OpenProcess(pid int) (Process, error) { |
408 | 408 |
container: container, |
409 | 409 |
} |
410 | 410 |
|
411 |
+ if err := process.registerCallback(); err != nil { |
|
412 |
+ err = &ContainerError{Container: container, Operation: operation, Err: err} |
|
413 |
+ logrus.Error(err) |
|
414 |
+ return nil, err |
|
415 |
+ } |
|
416 |
+ |
|
411 | 417 |
logrus.Debugf(title+" succeeded id=%s processid=%s", container.id, process.processID) |
412 | 418 |
runtime.SetFinalizer(process, closeProcess) |
413 | 419 |
return process, nil |
... | ... |
@@ -424,6 +445,14 @@ func (container *container) Close() error { |
424 | 424 |
return nil |
425 | 425 |
} |
426 | 426 |
|
427 |
+ if hcsCallbacksSupported { |
|
428 |
+ if err := container.unregisterCallback(); err != nil { |
|
429 |
+ err = &ContainerError{Container: container, Operation: operation, Err: err} |
|
430 |
+ logrus.Error(err) |
|
431 |
+ return err |
|
432 |
+ } |
|
433 |
+ } |
|
434 |
+ |
|
427 | 435 |
if err := hcsCloseComputeSystem(container.handle); err != nil { |
428 | 436 |
err = &ContainerError{Container: container, Operation: operation, Err: err} |
429 | 437 |
logrus.Error(err) |
... | ... |
@@ -441,7 +470,7 @@ func closeContainer(container *container) { |
441 | 441 |
container.Close() |
442 | 442 |
} |
443 | 443 |
|
444 |
-func (container *container) registerCallback(expectedNotification hcsNotification) (uintptr, error) { |
|
444 |
+func (container *container) registerCallback() error { |
|
445 | 445 |
callbackMapLock.Lock() |
446 | 446 |
defer callbackMapLock.Unlock() |
447 | 447 |
|
... | ... |
@@ -449,22 +478,24 @@ func (container *container) registerCallback(expectedNotification hcsNotificatio |
449 | 449 |
nextCallback++ |
450 | 450 |
|
451 | 451 |
context := ¬ifcationWatcherContext{ |
452 |
- expectedNotification: expectedNotification, |
|
453 |
- channel: make(chan error, 1), |
|
452 |
+ channels: newChannels(), |
|
454 | 453 |
} |
455 | 454 |
callbackMap[callbackNumber] = context |
456 | 455 |
|
457 | 456 |
var callbackHandle hcsCallback |
458 | 457 |
err := hcsRegisterComputeSystemCallback(container.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) |
459 | 458 |
if err != nil { |
460 |
- return 0, err |
|
459 |
+ return err |
|
461 | 460 |
} |
462 | 461 |
context.handle = callbackHandle |
462 |
+ container.callbackNumber = callbackNumber |
|
463 | 463 |
|
464 |
- return callbackNumber, nil |
|
464 |
+ return nil |
|
465 | 465 |
} |
466 | 466 |
|
467 |
-func (container *container) unregisterCallback(callbackNumber uintptr) error { |
|
467 |
+func (container *container) unregisterCallback() error { |
|
468 |
+ callbackNumber := container.callbackNumber |
|
469 |
+ |
|
468 | 470 |
callbackMapLock.Lock() |
469 | 471 |
defer callbackMapLock.Unlock() |
470 | 472 |
|
... | ... |
@@ -4,6 +4,7 @@ import ( |
4 | 4 |
"bufio" |
5 | 5 |
"encoding/binary" |
6 | 6 |
"errors" |
7 |
+ "fmt" |
|
7 | 8 |
"io" |
8 | 9 |
"os" |
9 | 10 |
"path/filepath" |
... | ... |
@@ -77,7 +78,7 @@ func readTombstones(path string) (map[string]([]string), error) { |
77 | 77 |
|
78 | 78 |
ts := make(map[string]([]string)) |
79 | 79 |
for s.Scan() { |
80 |
- t := s.Text()[1:] // skip leading `\` |
|
80 |
+ t := filepath.Join("Files", s.Text()[1:]) // skip leading `\` |
|
81 | 81 |
dir := filepath.Dir(t) |
82 | 82 |
ts[dir] = append(ts[dir], t) |
83 | 83 |
} |
... | ... |
@@ -107,6 +108,7 @@ func (r *legacyLayerReader) walkUntilCancelled() error { |
107 | 107 |
if path == r.root || path == filepath.Join(r.root, "tombstones.txt") || strings.HasSuffix(path, ".$wcidirs$") { |
108 | 108 |
return nil |
109 | 109 |
} |
110 |
+ |
|
110 | 111 |
r.result <- &fileEntry{path, info, nil} |
111 | 112 |
if !<-r.proceed { |
112 | 113 |
return errorIterationCanceled |
... | ... |
@@ -120,7 +122,7 @@ func (r *legacyLayerReader) walkUntilCancelled() error { |
120 | 120 |
} |
121 | 121 |
if dts, ok := ts[relPath]; ok { |
122 | 122 |
for _, t := range dts { |
123 |
- r.result <- &fileEntry{t, nil, nil} |
|
123 |
+ r.result <- &fileEntry{filepath.Join(r.root, t), nil, nil} |
|
124 | 124 |
if !<-r.proceed { |
125 | 125 |
return errorIterationCanceled |
126 | 126 |
} |
... | ... |
@@ -397,7 +399,10 @@ func (w *legacyLayerWriter) AddLink(name string, target string) error { |
397 | 397 |
} |
398 | 398 |
|
399 | 399 |
func (w *legacyLayerWriter) Remove(name string) error { |
400 |
- w.tombstones = append(w.tombstones, name) |
|
400 |
+ if !strings.HasPrefix(name, `Files\`) { |
|
401 |
+ return fmt.Errorf("invalid tombstone %s", name) |
|
402 |
+ } |
|
403 |
+ w.tombstones = append(w.tombstones, name[len(`Files\`):]) |
|
401 | 404 |
return nil |
402 | 405 |
} |
403 | 406 |
|
... | ... |
@@ -22,11 +22,11 @@ type ProcessError struct { |
22 | 22 |
} |
23 | 23 |
|
24 | 24 |
type process struct { |
25 |
- handle hcsProcess |
|
26 |
- processID int |
|
27 |
- container *container |
|
28 |
- cachedPipes *cachedPipes |
|
29 |
- killCallbackNumber uintptr |
|
25 |
+ handle hcsProcess |
|
26 |
+ processID int |
|
27 |
+ container *container |
|
28 |
+ cachedPipes *cachedPipes |
|
29 |
+ callbackNumber uintptr |
|
30 | 30 |
} |
31 | 31 |
|
32 | 32 |
type cachedPipes struct { |
... | ... |
@@ -101,7 +101,7 @@ func (process *process) Wait() error { |
101 | 101 |
logrus.Debugf(title+" processid=%d", process.processID) |
102 | 102 |
|
103 | 103 |
if hcsCallbacksSupported { |
104 |
- err := registerAndWaitForCallback(process, hcsNotificationProcessExited) |
|
104 |
+ err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, nil) |
|
105 | 105 |
if err != nil { |
106 | 106 |
err := &ProcessError{Operation: operation, Process: process, Err: err} |
107 | 107 |
logrus.Error(err) |
... | ... |
@@ -128,7 +128,7 @@ func (process *process) WaitTimeout(timeout time.Duration) error { |
128 | 128 |
logrus.Debugf(title+" processid=%d", process.processID) |
129 | 129 |
|
130 | 130 |
if hcsCallbacksSupported { |
131 |
- err := registerAndWaitForCallbackTimeout(process, hcsNotificationProcessExited, timeout) |
|
131 |
+ err := waitForNotification(process.callbackNumber, hcsNotificationProcessExited, &timeout) |
|
132 | 132 |
if err == ErrTimeout { |
133 | 133 |
return ErrTimeout |
134 | 134 |
} else if err != nil { |
... | ... |
@@ -344,6 +344,14 @@ func (process *process) Close() error { |
344 | 344 |
return nil |
345 | 345 |
} |
346 | 346 |
|
347 |
+ if hcsCallbacksSupported { |
|
348 |
+ if err := process.unregisterCallback(); err != nil { |
|
349 |
+ err = &ProcessError{Operation: operation, Process: process, Err: err} |
|
350 |
+ logrus.Error(err) |
|
351 |
+ return err |
|
352 |
+ } |
|
353 |
+ } |
|
354 |
+ |
|
347 | 355 |
if err := hcsCloseProcess(process.handle); err != nil { |
348 | 356 |
err = &ProcessError{Operation: operation, Process: process, Err: err} |
349 | 357 |
logrus.Error(err) |
... | ... |
@@ -361,7 +369,7 @@ func closeProcess(process *process) { |
361 | 361 |
process.Close() |
362 | 362 |
} |
363 | 363 |
|
364 |
-func (process *process) registerCallback(expectedNotification hcsNotification) (uintptr, error) { |
|
364 |
+func (process *process) registerCallback() error { |
|
365 | 365 |
callbackMapLock.Lock() |
366 | 366 |
defer callbackMapLock.Unlock() |
367 | 367 |
|
... | ... |
@@ -369,22 +377,24 @@ func (process *process) registerCallback(expectedNotification hcsNotification) ( |
369 | 369 |
nextCallback++ |
370 | 370 |
|
371 | 371 |
context := ¬ifcationWatcherContext{ |
372 |
- expectedNotification: expectedNotification, |
|
373 |
- channel: make(chan error, 1), |
|
372 |
+ channels: newChannels(), |
|
374 | 373 |
} |
375 | 374 |
callbackMap[callbackNumber] = context |
376 | 375 |
|
377 | 376 |
var callbackHandle hcsCallback |
378 | 377 |
err := hcsRegisterProcessCallback(process.handle, notificationWatcherCallback, callbackNumber, &callbackHandle) |
379 | 378 |
if err != nil { |
380 |
- return 0, err |
|
379 |
+ return err |
|
381 | 380 |
} |
382 | 381 |
context.handle = callbackHandle |
382 |
+ process.callbackNumber = callbackNumber |
|
383 | 383 |
|
384 |
- return callbackNumber, nil |
|
384 |
+ return nil |
|
385 | 385 |
} |
386 | 386 |
|
387 |
-func (process *process) unregisterCallback(callbackNumber uintptr) error { |
|
387 |
+func (process *process) unregisterCallback() error { |
|
388 |
+ callbackNumber := process.callbackNumber |
|
389 |
+ |
|
388 | 390 |
callbackMapLock.Lock() |
389 | 391 |
defer callbackMapLock.Unlock() |
390 | 392 |
handle := callbackMap[callbackNumber].handle |
... | ... |
@@ -1,6 +1,7 @@ |
1 | 1 |
package hcsshim |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "github.com/Sirupsen/logrus" |
|
4 | 5 |
"syscall" |
5 | 6 |
"time" |
6 | 7 |
) |
... | ... |
@@ -10,11 +11,6 @@ type waitable interface { |
10 | 10 |
hcsWait(timeout uint32) (bool, error) |
11 | 11 |
} |
12 | 12 |
|
13 |
-type callbackable interface { |
|
14 |
- registerCallback(expectedNotification hcsNotification) (uintptr, error) |
|
15 |
- unregisterCallback(callbackNumber uintptr) error |
|
16 |
-} |
|
17 |
- |
|
18 | 13 |
func waitTimeoutHelper(object waitable, timeout time.Duration) (bool, error) { |
19 | 14 |
var ( |
20 | 15 |
millis uint32 |
... | ... |
@@ -52,62 +48,62 @@ func waitForSingleObject(handle syscall.Handle, timeout uint32) (bool, error) { |
52 | 52 |
} |
53 | 53 |
} |
54 | 54 |
|
55 |
-func processAsyncHcsResult(object callbackable, err error, resultp *uint16, expectedNotification hcsNotification, timeout *time.Duration) error { |
|
55 |
+func processAsyncHcsResult(err error, resultp *uint16, callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { |
|
56 | 56 |
err = processHcsResult(err, resultp) |
57 | 57 |
if err == ErrVmcomputeOperationPending { |
58 |
- if timeout != nil { |
|
59 |
- err = registerAndWaitForCallbackTimeout(object, expectedNotification, *timeout) |
|
60 |
- } else { |
|
61 |
- err = registerAndWaitForCallback(object, expectedNotification) |
|
62 |
- } |
|
58 |
+ return waitForNotification(callbackNumber, expectedNotification, timeout) |
|
63 | 59 |
} |
64 | 60 |
|
65 | 61 |
return err |
66 | 62 |
} |
67 | 63 |
|
68 |
-func registerAndWaitForCallbackTimeout(object callbackable, expectedNotification hcsNotification, timeout time.Duration) error { |
|
69 |
- callbackNumber, err := object.registerCallback(expectedNotification) |
|
70 |
- if err != nil { |
|
71 |
- return err |
|
72 |
- } |
|
73 |
- defer object.unregisterCallback(callbackNumber) |
|
74 |
- |
|
75 |
- return waitForNotificationTimeout(callbackNumber, timeout) |
|
76 |
-} |
|
77 |
- |
|
78 |
-func registerAndWaitForCallback(object callbackable, expectedNotification hcsNotification) error { |
|
79 |
- callbackNumber, err := object.registerCallback(expectedNotification) |
|
80 |
- if err != nil { |
|
81 |
- return err |
|
82 |
- } |
|
83 |
- defer object.unregisterCallback(callbackNumber) |
|
84 |
- |
|
85 |
- return waitForNotification(callbackNumber) |
|
86 |
-} |
|
87 |
- |
|
88 |
-func waitForNotificationTimeout(callbackNumber uintptr, timeout time.Duration) error { |
|
64 |
+func waitForNotification(callbackNumber uintptr, expectedNotification hcsNotification, timeout *time.Duration) error { |
|
89 | 65 |
callbackMapLock.RLock() |
90 |
- channel := callbackMap[callbackNumber].channel |
|
66 |
+ channels := callbackMap[callbackNumber].channels |
|
91 | 67 |
callbackMapLock.RUnlock() |
92 | 68 |
|
93 |
- timer := time.NewTimer(timeout) |
|
94 |
- defer timer.Stop() |
|
95 |
- |
|
96 |
- select { |
|
97 |
- case err := <-channel: |
|
98 |
- return err |
|
99 |
- case <-timer.C: |
|
100 |
- return ErrTimeout |
|
69 |
+ expectedChannel := channels[expectedNotification] |
|
70 |
+ if expectedChannel == nil { |
|
71 |
+ logrus.Errorf("unknown notification type in waitForNotification %x", expectedNotification) |
|
101 | 72 |
} |
102 |
-} |
|
103 |
- |
|
104 |
-func waitForNotification(callbackNumber uintptr) error { |
|
105 |
- callbackMapLock.RLock() |
|
106 |
- channel := callbackMap[callbackNumber].channel |
|
107 |
- callbackMapLock.RUnlock() |
|
108 | 73 |
|
74 |
+ if timeout != nil { |
|
75 |
+ timer := time.NewTimer(*timeout) |
|
76 |
+ defer timer.Stop() |
|
77 |
+ |
|
78 |
+ select { |
|
79 |
+ case err := <-expectedChannel: |
|
80 |
+ return err |
|
81 |
+ case err := <-channels[hcsNotificationSystemExited]: |
|
82 |
+ // If the expected notification is hcsNotificationSystemExited which of the two selects |
|
83 |
+ // chosen is random. Return the raw error if hcsNotificationSystemExited is expected |
|
84 |
+ if channels[hcsNotificationSystemExited] == expectedChannel { |
|
85 |
+ return err |
|
86 |
+ } |
|
87 |
+ return ErrUnexpectedContainerExit |
|
88 |
+ case err := <-channels[hcsNotificationServiceDisconnect]: |
|
89 |
+ // hcsNotificationServiceDisconnect should never be an expected notification |
|
90 |
+ // it does not need the same handling as hcsNotificationSystemExited |
|
91 |
+ logrus.Error(err) |
|
92 |
+ return ErrUnexpectedProcessAbort |
|
93 |
+ case <-timer.C: |
|
94 |
+ return ErrTimeout |
|
95 |
+ } |
|
96 |
+ } |
|
109 | 97 |
select { |
110 |
- case err := <-channel: |
|
98 |
+ case err := <-expectedChannel: |
|
111 | 99 |
return err |
100 |
+ case err := <-channels[hcsNotificationSystemExited]: |
|
101 |
+ // If the expected notification is hcsNotificationSystemExited which of the two selects |
|
102 |
+ // chosen is random. Return the raw error if hcsNotificationSystemExited is expected |
|
103 |
+ if channels[hcsNotificationSystemExited] == expectedChannel { |
|
104 |
+ return err |
|
105 |
+ } |
|
106 |
+ return ErrUnexpectedContainerExit |
|
107 |
+ case err := <-channels[hcsNotificationServiceDisconnect]: |
|
108 |
+ // hcsNotificationServiceDisconnect should never be an expected notification |
|
109 |
+ // it does not need the same handling as hcsNotificationSystemExited |
|
110 |
+ logrus.Error(err) |
|
111 |
+ return ErrUnexpectedProcessAbort |
|
112 | 112 |
} |
113 | 113 |
} |