Browse code

Rebased changes to return on first start's error

Signed-off-by: Michael Crosby <michael@docker.com>

Michael Crosby authored on 2014/08/13 10:03:11
Showing 2 changed files
... ...
@@ -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
 	}