@@ -88,6 +88,7 @@ func newNGINXController() ingress.Controller {
88
88
isIPV6Enabled : isIPv6Enabled (),
89
89
resolver : h ,
90
90
ports : & config.ListenPorts {},
91
+ stopCh : make (chan struct {}),
91
92
}
92
93
93
94
fcgiListener , err := net .Listen ("unix" , fastCGISocket )
@@ -161,19 +162,31 @@ type NGINXController struct {
161
162
162
163
isSSLPassthroughEnabled bool
163
164
165
+ isStopping bool
166
+
164
167
proxy * proxy
165
168
166
169
ports * config.ListenPorts
167
170
168
171
backendDefaults defaults.Backend
172
+ stopCh chan struct {}
169
173
}
170
174
171
175
// Start start a new NGINX master process running in foreground.
172
176
func (n * NGINXController ) Start () {
173
177
glog .Info ("starting NGINX process..." )
178
+ n .isStopping = false
174
179
175
180
done := make (chan error , 1 )
176
181
cmd := exec .Command (n .binary , "-c" , cfgPath )
182
+
183
+ // put nginx in another process group to prevent it
184
+ // to receive signals meant for the controller
185
+ cmd .SysProcAttr = & syscall.SysProcAttr {
186
+ Setpgid : true ,
187
+ Pgid : 0 ,
188
+ }
189
+
177
190
n .start (cmd , done )
178
191
179
192
// if the nginx master process dies the workers continue to process requests,
@@ -202,8 +215,43 @@ NGINX master process died (%v): %v
202
215
conn .Close ()
203
216
time .Sleep (1 * time .Second )
204
217
}
205
- // start a new nginx master process
206
- n .start (cmd , done )
218
+ // restart a new nginx master process if the controller
219
+ // is not being stopped
220
+ if n .isStopping {
221
+ n .stopCh <- struct {}{}
222
+ } else {
223
+ n .start (cmd , done )
224
+ }
225
+ }
226
+ }
227
+
228
+ // OnStop gracefully stops the NGINX master process.
229
+ func (n * NGINXController ) OnStop () error {
230
+ glog .Info ("stopping NGINX process..." )
231
+ n .isStopping = true
232
+
233
+ o , err := exec .Command (n .binary , "-s" , "quit" , "-c" , cfgPath ).CombinedOutput ()
234
+ if err != nil {
235
+ glog .Errorf ("%v\n %v" , err , string (o ))
236
+ }
237
+
238
+ // TODO: If we keep the modified Controller interface
239
+ // should this be moved as a generic timeout control for the backend to stop
240
+ // on time ?
241
+ timer := time .NewTimer (60 * time .Second )
242
+ defer timer .Stop ()
243
+
244
+ for {
245
+ select {
246
+ case <- n .stopCh :
247
+ return nil
248
+ case <- timer .C :
249
+ glog .Error ("Timeout while waiting for nginx to gracefully shutdown" )
250
+ o , err := exec .Command (n .binary , "-s" , "stop" , "-c" , cfgPath ).CombinedOutput ()
251
+ if err != nil {
252
+ return fmt .Errorf ("%v\n %v" , err , string (o ))
253
+ }
254
+ }
207
255
}
208
256
}
209
257
0 commit comments