Browse code

Fix race condition between cleanup and Start

There was problem when Start might be before cleanup

Fixes #6904

Signed-off-by: Alexandr Morozov <lk4d4math@gmail.com>

Alexandr Morozov authored on 2014/08/27 00:53:43
Showing 1 changed files
... ...
@@ -101,15 +101,16 @@ func (m *containerMonitor) Start() error {
101 101
 	var (
102 102
 		err        error
103 103
 		exitStatus int
104
+		// this variable indicates where we in execution flow:
105
+		// before Run or after
106
+		afterRun bool
104 107
 	)
105 108
 
106
-	// this variable indicates that we under container.Lock
107
-	underLock := true
108
-
109 109
 	// ensure that when the monitor finally exits we release the networking and unmount the rootfs
110 110
 	defer func() {
111
-		if !underLock {
111
+		if afterRun {
112 112
 			m.container.Lock()
113
+			m.container.State.SetStopped(exitStatus)
113 114
 			defer m.container.Unlock()
114 115
 		}
115 116
 		m.Close()
... ...
@@ -146,15 +147,13 @@ func (m *containerMonitor) Start() error {
146 146
 		}
147 147
 
148 148
 		// here container.Lock is already lost
149
-		underLock = false
149
+		afterRun = true
150 150
 
151 151
 		m.resetMonitor(err == nil && exitStatus == 0)
152 152
 
153 153
 		if m.shouldRestart(exitStatus) {
154 154
 			m.container.State.SetRestarting(exitStatus)
155
-
156 155
 			m.container.LogEvent("die")
157
-
158 156
 			m.resetContainer()
159 157
 
160 158
 			// sleep with a small time increment between each restart to help avoid issues cased by quickly
... ...
@@ -164,24 +163,14 @@ func (m *containerMonitor) Start() error {
164 164
 			// we need to check this before reentering the loop because the waitForNextRestart could have
165 165
 			// been terminated by a request from a user
166 166
 			if m.shouldStop {
167
-				m.container.State.SetStopped(exitStatus)
168
-
169 167
 				return err
170 168
 			}
171
-
172 169
 			continue
173 170
 		}
174
-
175
-		m.container.State.SetStopped(exitStatus)
176
-
177 171
 		m.container.LogEvent("die")
178
-
179 172
 		m.resetContainer()
180
-
181
-		break
173
+		return err
182 174
 	}
183
-
184
-	return err
185 175
 }
186 176
 
187 177
 // resetMonitor resets the stateful fields on the containerMonitor based on the