@@ -114,7 +114,11 @@ func (a *App) Shutdown() {
114
114
go func (s * http.Server ) {
115
115
defer wg .Done ()
116
116
err := s .Shutdown (context .Background ())
117
- logger .Printf ("ZeroDT: server '%v' is shutdown with: '%v'" , s .Addr , err )
117
+ if err != nil {
118
+ logger .Printf ("ZeroDT: server %s has been shutdown with: %v" , s .Addr , err )
119
+ return
120
+ }
121
+ logger .Printf ("ZeroDT: server %s has been shutdown" , s .Addr )
118
122
}(s )
119
123
}
120
124
@@ -126,7 +130,7 @@ func (a *App) Shutdown() {
126
130
// the inherited ones. It also serves the servers and monitors OS
127
131
// signals.
128
132
func (a * App ) ListenAndServe () error {
129
- inherited , m , err := inherit ()
133
+ inherited , messenger , err := inherit ()
130
134
if err != nil {
131
135
logger .Printf ("ZeroDT: failed to inherit listeners with: '%v'" , err )
132
136
return err
@@ -155,45 +159,53 @@ func (a *App) ListenAndServe() error {
155
159
for _ , s := range a .servers {
156
160
go func (s * http.Server ) {
157
161
defer srvWG .Done ()
162
+ // Make sure Shutdown is not blocked event if
163
+ // notifyListener.Accept() not call.
164
+ servedOnce := & doneOnce {wg : & a .served }
165
+ defer servedOnce .Done ()
166
+ // Make sure startWG.Wait() is not blocked in case of error
167
+ // in acquireOrCreateListener.
168
+ startOnce := & doneOnce {wg : & startWG }
169
+ defer startOnce .Done ()
170
+
158
171
l , err := e .acquireOrCreateListener ("tcp" , s .Addr )
159
- startWG .Done ()
160
172
if err != nil {
161
173
// TODO: error channel
162
- logger .Printf ("ZeroDT: failed to listen on '%v' with %v" , s .Addr , err )
174
+ logger .Printf ("ZeroDT: failed to listen on %v with %v" , s .Addr , err )
163
175
return
164
176
}
177
+ // A server is about to Serve and already listen.
178
+ startOnce .Done ()
179
+ // Wait for parent to start if set.
165
180
parentWG .Wait ()
166
181
if finalErr != nil {
167
- logger .Printf ("ZeroDT: server '%v' has finished serving with %v" , s .Addr , err )
182
+ logger .Printf ("ZeroDT: server %v has finished serving with %v" , s .Addr , err )
168
183
return
169
184
}
170
- err = s .Serve (& notifyListener {Listener : tcpKeepAliveListener {l }, wg : & a . served })
171
- logger .Printf ("ZeroDT: server '%v' has finished serving with %v" , s .Addr , err )
185
+ err = s .Serve (& notifyListener {Listener : tcpKeepAliveListener {l }, doneOnce : servedOnce })
186
+ logger .Printf ("ZeroDT: server %v has finished serving with %v" , s .Addr , err )
172
187
}(s )
173
188
}
174
189
175
190
// Wait for all listeners to start listening.
176
191
startWG .Wait ()
177
192
178
- if m != nil {
179
- finalErr = protocolActAsChild (m , a .waitChildTimeout , a .waitParentShutdownTimeout , a .PreParentExitFn )
193
+ if messenger != nil {
194
+ finalErr = protocolActAsChild (messenger , a .waitChildTimeout , a .waitParentShutdownTimeout , a .PreParentExitFn )
180
195
}
181
-
182
196
if finalErr == nil {
183
197
a .PreServeFn (e .didInherit ())
184
198
}
185
199
186
200
// Allow serverse's goroutines to start serving.
187
201
parentWG .Done ()
188
-
189
- // Wait for all server's. They may fail or be stopped by
190
- // calling 'Shutdown'.
202
+ // Wait for all server's. They may fail or be stopped by calling
203
+ // Shutdown.
191
204
srvWG .Wait ()
192
-
193
205
// Stop handling OS signals and wait for it's goroutine.
194
206
sigCancelFunc ()
195
207
sigWG .Wait ()
196
-
208
+ logger . Printf ( "ZeroDT: exit" )
197
209
return finalErr
198
210
}
199
211
@@ -205,11 +217,18 @@ func (a *App) handleSignals(ctx context.Context, wg *sync.WaitGroup, e *exchange
205
217
signal .Notify (signals , syscall .SIGTERM , syscall .SIGINT , syscall .SIGUSR2 )
206
218
defer signal .Stop (signals )
207
219
220
+ wasShutdown := false
221
+
208
222
CatchSignals:
209
223
for {
210
224
select {
211
225
// Exit.
212
226
case <- ctx .Done ():
227
+ if ! wasShutdown {
228
+ // Possbile in case of errors in 'http.Serve'.
229
+ // It's needed to start shutdown process any way.
230
+ a .Shutdown ()
231
+ }
213
232
return
214
233
// OS signal.
215
234
case s := <- signals :
@@ -218,6 +237,7 @@ CatchSignals:
218
237
// Shutdown servers. No exit here.
219
238
case syscall .SIGINT , syscall .SIGTERM :
220
239
a .Shutdown ()
240
+ wasShutdown = true
221
241
// Fork/Exec a child and shutdown.
222
242
case syscall .SIGUSR2 :
223
243
_ , f , err := forkExec (e .activeFiles ())
@@ -233,6 +253,7 @@ CatchSignals:
233
253
// Nothing to do with errors.
234
254
protocolActAsParent (m , a .waitChildTimeout , a .waitParentShutdownTimeout , func () {
235
255
a .Shutdown ()
256
+ wasShutdown = true
236
257
})
237
258
}
238
259
}
0 commit comments