Signed-off-by: Darren Stahl <darst@microsoft.com>
| ... | ... |
@@ -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 |
} |