Signed-off-by: Michael Crosby <michael@docker.com>
| ... | ... |
@@ -1081,22 +1081,14 @@ func (container *Container) startLoggingToDisk() error {
|
| 1081 | 1081 |
func (container *Container) waitForStart() error {
|
| 1082 | 1082 |
container.monitor = newContainerMonitor(container, container.hostConfig.RestartPolicy) |
| 1083 | 1083 |
|
| 1084 |
- var ( |
|
| 1085 |
- cErr = utils.Go(container.monitor.Start) |
|
| 1086 |
- waitStart = make(chan struct{})
|
|
| 1087 |
- ) |
|
| 1088 |
- |
|
| 1089 |
- go func() {
|
|
| 1090 |
- container.State.WaitRunning(-1 * time.Second) |
|
| 1091 |
- close(waitStart) |
|
| 1092 |
- }() |
|
| 1093 |
- |
|
| 1094 |
- // Start should not return until the process is actually running |
|
| 1084 |
+ // block until we either receive an error from the initial start of the container's |
|
| 1085 |
+ // process or until the process is running in the container |
|
| 1095 | 1086 |
select {
|
| 1096 |
- case <-waitStart: |
|
| 1097 |
- case err := <-cErr: |
|
| 1087 |
+ case <-container.monitor.startSignal: |
|
| 1088 |
+ case err := <-utils.Go(container.monitor.Start): |
|
| 1098 | 1089 |
return err |
| 1099 | 1090 |
} |
| 1091 |
+ |
|
| 1100 | 1092 |
return nil |
| 1101 | 1093 |
} |
| 1102 | 1094 |
|
| ... | ... |
@@ -35,6 +35,10 @@ type containerMonitor struct {
|
| 35 | 35 |
// either because docker or the user asked for the container to be stopped |
| 36 | 36 |
shouldStop bool |
| 37 | 37 |
|
| 38 |
+ // startSignal signals with the initial process has launched after calling Start |
|
| 39 |
+ // on the monitor |
|
| 40 |
+ startSignal chan struct{}
|
|
| 41 |
+ |
|
| 38 | 42 |
// stopChan is used to signal to the monitor whenever there is a wait for the |
| 39 | 43 |
// next restart so that the timeIncrement is not honored and the user is not |
| 40 | 44 |
// left waiting for nothing to happen during this time |
| ... | ... |
@@ -48,12 +52,15 @@ type containerMonitor struct {
|
| 48 | 48 |
lastStartTime time.Time |
| 49 | 49 |
} |
| 50 | 50 |
|
| 51 |
+// newContainerMonitor returns an initialized containerMonitor for the provided container |
|
| 52 |
+// honoring the provided restart policy |
|
| 51 | 53 |
func newContainerMonitor(container *Container, policy runconfig.RestartPolicy) *containerMonitor {
|
| 52 | 54 |
return &containerMonitor{
|
| 53 | 55 |
container: container, |
| 54 | 56 |
restartPolicy: policy, |
| 55 | 57 |
timeIncrement: defaultTimeIncrement, |
| 56 | 58 |
stopChan: make(chan struct{}, 1),
|
| 59 |
+ startSignal: make(chan struct{}, 1),
|
|
| 57 | 60 |
} |
| 58 | 61 |
} |
| 59 | 62 |
|
| ... | ... |
@@ -119,6 +126,14 @@ func (m *containerMonitor) Start() error {
|
| 119 | 119 |
m.lastStartTime = time.Now() |
| 120 | 120 |
|
| 121 | 121 |
if exitStatus, err = m.container.daemon.Run(m.container, pipes, m.callback); err != nil {
|
| 122 |
+ // if we receive an internal error from the initial start of a container then lets |
|
| 123 |
+ // return it instead of entering the restart loop |
|
| 124 |
+ if m.container.RestartCount == 1 {
|
|
| 125 |
+ m.resetContainer() |
|
| 126 |
+ |
|
| 127 |
+ return err |
|
| 128 |
+ } |
|
| 129 |
+ |
|
| 122 | 130 |
utils.Errorf("Error running container: %s", err)
|
| 123 | 131 |
} |
| 124 | 132 |
|
| ... | ... |
@@ -230,6 +245,9 @@ func (m *containerMonitor) callback(command *execdriver.Command) {
|
| 230 | 230 |
|
| 231 | 231 |
m.container.State.SetRunning(command.Pid()) |
| 232 | 232 |
|
| 233 |
+ // signal that the process has started |
|
| 234 |
+ close(m.startSignal) |
|
| 235 |
+ |
|
| 233 | 236 |
if err := m.container.ToDisk(); err != nil {
|
| 234 | 237 |
utils.Debugf("%s", err)
|
| 235 | 238 |
} |