os.Exit
or log.Fatal
and friends made in function using defer
CRT-D0011defer tick.Stop()
will not run 421 defer tick.Stop()
422 totalMem, err := memory.MemTotal()
423 if err != nil {
424 log.Fatal("fail to get total memory:%s", zap.Error(err)) 425 }
426 log.Info("memory info", zap.Uint64("total-mem", totalMem))
427 cfg := c.opt.GetPDServerConfig()
defer logutil.LogPanic()
will not run593 if err == nil {
594 log.ReplaceGlobals(cfg.Logger, cfg.LogProps)
595 } else {
596 log.Fatal("initialize logger error", errs.ZapError(err))597 }
598 // Flushing any buffered log entries
599 log.Sync()
defer logutil.LogPanic()
will not run465 if err == nil {
466 log.ReplaceGlobals(cfg.Logger, cfg.LogProps)
467 } else {
468 log.Fatal("initialize logger error", errs.ZapError(err))469 }
470 // Flushing any buffered log entries
471 log.Sync()
defer logutil.LogPanic()
will not run394 if err == nil {
395 log.ReplaceGlobals(cfg.Logger, cfg.LogProps)
396 } else {
397 log.Fatal("initialize logger error", errs.ZapError(err))398 }
399 // Flushing any buffered log entries
400 log.Sync()
defer s.ServerLoopWgDone()
will not run249 if s.IsClosed() {
250 log.Info("mux stopped serving", errs.ZapError(err))
251 } else {
252 log.Fatal("mux stopped serving unexpectedly", errs.ZapError(err))253 }
254 }
255}
Calls to os.Exit
or log.Fatal
and friends made in function with defer
statements do not execute those statements if control reaches the
os.Exit
or log.Fatal
and friends.
If the os.Exit
function happens in a goroutine, all the goroutines (including
the main one) will terminate immediately without executing any deferred statement.
Internally, log.Fatal
and friends (log.Fatalln
and log.Fatalf
) internally
uses os.Exit(1)
, which results in the immediate termination of the program
without executing the deferred statements.
It is recommended to handle such cases gracefully so that deferred statements are executed to necessary operations such as closing open file descriptors, cleanup, etc.
defer os.Remove(filename)
if bad {
log.Fatalf("something bad happened")
}
defer os.Remove(filename)
if bad {
log.Printf("something bad happened")
return // exits with "exit status 0"
}
retcode := 0
defer func() { os.Exit(retcode) }
defer os.Remove(filename)
if bad {
log.Printf("something bad happened")
retcode = 1
return // exits with "exit status 1" because of topmost `defer` call
}