go-imap
go-imap copied to clipboard
Hang in logout in panic
When there is a panic while processing inbox messages the defer logout is hanging process. (and prevents seeing the stack trace).
Context:
- listen update in a go routine
- use IdleWithFallback in a go routine
- messages processing in main routine (panic here hangs)
Workaround do not logout in panic case: defer func() { //prevents logout while panic, it hangs the process and prevents seeing failure stack if r := recover(); r != nil { fmt.Println("Recovered in f", r) panic(r) } else { c.Logout() } }()
@Crapulax Did anything come of this?
Sorry, but I do not understand your question. What do you mean?
If you ask, if I had a feedback, answer is no. Now, I am using above mentioned solution and it works just fine, I can catch the underlying error. At the end of the day, my issue was not so much with the freeze but with the inability to see the triggering panic stack. But I guess that yes it should be handled in the library. There is so many channels involved in it that it is easy to run into deadlocks and by the way not suspect an issue, at first glance, within your code.
Thank you for sharing your experience.
I'm not sure what should be done here. What happens if you replace defer c.Logout()
with defer c.Terminate()
?
package main
import (
"fmt"
"github.com/emersion/go-imap/client"
)
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("PANIC", err)
}
}()
// Connect to server
c, err := client.DialTLS("mail.example.org:993", nil)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Connected")
// Don't forget to logout
defer c.Logout()
// Login
if err := c.Login("username", "password"); err != nil {
fmt.Println(err)
return
}
fmt.Println("Logged in")
// panic
panic("PANIC will be catch by Logout!!!")
}
For fix this:
defer func() {
//prevents logout while panic, it hangs the process and prevents seeing failure stack
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
panic(r)
} else {
c.Logout()
}
}()
defer func () {
go c.Logout()
}()