mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-18 01:57:02 +00:00
Graceful shutdown on error for httpd, smtpd, pop3d
This commit is contained in:
@@ -193,11 +193,11 @@ func parseSMTPConfig() error {
|
|||||||
}
|
}
|
||||||
addr := net.ParseIP(str)
|
addr := net.ParseIP(str)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, str)
|
||||||
}
|
}
|
||||||
addr = addr.To4()
|
addr = addr.To4()
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, err)
|
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, str)
|
||||||
}
|
}
|
||||||
smtpConfig.IP4address = addr
|
smtpConfig.IP4address = addr
|
||||||
|
|
||||||
@@ -264,11 +264,11 @@ func parsePOP3Config() error {
|
|||||||
}
|
}
|
||||||
addr := net.ParseIP(str)
|
addr := net.ParseIP(str)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, str)
|
||||||
}
|
}
|
||||||
addr = addr.To4()
|
addr = addr.To4()
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, err)
|
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, str)
|
||||||
}
|
}
|
||||||
pop3Config.IP4address = addr
|
pop3Config.IP4address = addr
|
||||||
|
|
||||||
@@ -307,11 +307,11 @@ func parseWebConfig() error {
|
|||||||
}
|
}
|
||||||
addr := net.ParseIP(str)
|
addr := net.ParseIP(str)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, err)
|
return fmt.Errorf("Failed to parse [%v]%v: '%v'", section, option, str)
|
||||||
}
|
}
|
||||||
addr = addr.To4()
|
addr = addr.To4()
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, err)
|
return fmt.Errorf("Failed to parse [%v]%v: '%v' not IPv4!", section, option, str)
|
||||||
}
|
}
|
||||||
webConfig.IP4address = addr
|
webConfig.IP4address = addr
|
||||||
|
|
||||||
|
|||||||
@@ -75,8 +75,8 @@ func Start() {
|
|||||||
listener, err = net.Listen("tcp", addr)
|
listener, err = net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("HTTP failed to start TCP4 listener: %v", err)
|
log.Errorf("HTTP failed to start TCP4 listener: %v", err)
|
||||||
// TODO More graceful early-shutdown procedure
|
emergencyShutdown()
|
||||||
panic(err)
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listener go routine
|
// Listener go routine
|
||||||
@@ -104,7 +104,8 @@ func serve() {
|
|||||||
// Nop
|
// Nop
|
||||||
default:
|
default:
|
||||||
log.Errorf("HTTP server failed: %v", err)
|
log.Errorf("HTTP server failed: %v", err)
|
||||||
// TODO shutdown?
|
emergencyShutdown()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,3 +142,12 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
log.Errorf("HTTP failed to write response: %v", err)
|
log.Errorf("HTTP failed to write response: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func emergencyShutdown() {
|
||||||
|
// Shutdown Inbucket
|
||||||
|
select {
|
||||||
|
case _ = <-globalShutdown:
|
||||||
|
default:
|
||||||
|
close(globalShutdown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -47,16 +47,20 @@ func (s *Server) Start() {
|
|||||||
cfg.IP4address, cfg.IP4port))
|
cfg.IP4address, cfg.IP4port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("POP3 Failed to build tcp4 address: %v", err)
|
log.Errorf("POP3 Failed to build tcp4 address: %v", err)
|
||||||
// TODO More graceful early-shutdown procedure
|
// serve() never called, so we do local shutdown here
|
||||||
panic(err)
|
close(s.localShutdown)
|
||||||
|
s.emergencyShutdown()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("POP3 listening on TCP4 %v", addr)
|
log.Infof("POP3 listening on TCP4 %v", addr)
|
||||||
s.listener, err = net.ListenTCP("tcp4", addr)
|
s.listener, err = net.ListenTCP("tcp4", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("POP3 failed to start tcp4 listener: %v", err)
|
log.Errorf("POP3 failed to start tcp4 listener: %v", err)
|
||||||
// TODO More graceful early-shutdown procedure
|
// serve() never called, so we do local shutdown here
|
||||||
panic(err)
|
close(s.localShutdown)
|
||||||
|
s.emergencyShutdown()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Listener go routine
|
// Listener go routine
|
||||||
@@ -100,9 +104,9 @@ func (s *Server) serve() {
|
|||||||
close(s.localShutdown)
|
close(s.localShutdown)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
// TODO Implement a max error counter before shutdown?
|
close(s.localShutdown)
|
||||||
// or maybe attempt to restart smtpd
|
s.emergencyShutdown()
|
||||||
panic(err)
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -113,6 +117,15 @@ func (s *Server) serve() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) emergencyShutdown() {
|
||||||
|
// Shutdown Inbucket
|
||||||
|
select {
|
||||||
|
case _ = <-s.globalShutdown:
|
||||||
|
default:
|
||||||
|
close(s.globalShutdown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Drain causes the caller to block until all active POP3 sessions have finished
|
// Drain causes the caller to block until all active POP3 sessions have finished
|
||||||
func (s *Server) Drain() {
|
func (s *Server) Drain() {
|
||||||
// Wait for listener to exit
|
// Wait for listener to exit
|
||||||
|
|||||||
@@ -78,16 +78,20 @@ func (s *Server) Start() {
|
|||||||
cfg.IP4address, cfg.IP4port))
|
cfg.IP4address, cfg.IP4port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Failed to build tcp4 address: %v", err)
|
log.Errorf("Failed to build tcp4 address: %v", err)
|
||||||
// TODO More graceful early-shutdown procedure
|
// serve() never called, so we do local shutdown here
|
||||||
panic(err)
|
close(s.localShutdown)
|
||||||
|
s.emergencyShutdown()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("SMTP listening on TCP4 %v", addr)
|
log.Infof("SMTP listening on TCP4 %v", addr)
|
||||||
s.listener, err = net.ListenTCP("tcp4", addr)
|
s.listener, err = net.ListenTCP("tcp4", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("SMTP failed to start tcp4 listener: %v", err)
|
log.Errorf("SMTP failed to start tcp4 listener: %v", err)
|
||||||
// TODO More graceful early-shutdown procedure
|
// serve() never called, so we do local shutdown here
|
||||||
panic(err)
|
close(s.localShutdown)
|
||||||
|
s.emergencyShutdown()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.storeMessages {
|
if !s.storeMessages {
|
||||||
@@ -141,9 +145,9 @@ func (s *Server) serve() {
|
|||||||
close(s.localShutdown)
|
close(s.localShutdown)
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
// TODO Implement a max error counter before shutdown?
|
close(s.localShutdown)
|
||||||
// or maybe attempt to restart smtpd
|
s.emergencyShutdown()
|
||||||
panic(err)
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -155,6 +159,15 @@ func (s *Server) serve() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) emergencyShutdown() {
|
||||||
|
// Shutdown Inbucket
|
||||||
|
select {
|
||||||
|
case _ = <-s.globalShutdown:
|
||||||
|
default:
|
||||||
|
close(s.globalShutdown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Drain causes the caller to block until all active SMTP sessions have finished
|
// Drain causes the caller to block until all active SMTP sessions have finished
|
||||||
func (s *Server) Drain() {
|
func (s *Server) Drain() {
|
||||||
// Wait for listener to exit
|
// Wait for listener to exit
|
||||||
|
|||||||
Reference in New Issue
Block a user