Discussion:
[go-nuts] Why I can't to catch all panics?
u***@gmail.com
2015-07-30 17:11:54 UTC
Permalink
I have an API service build with http lib. I have a recover inside http
handler:

132 func execApiMethod(w http.ResponseWriter, r *http.Request) {
133 defer func() {
134 if r := recover(); r != nil {
135 server.Logger.Print("Error: ", r)
136 }
137 }()
138
139 // doing some dirty stuf
But my app is crashing time after time with trace:


panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x58 pc=0x56053d]
crypto/tls.(*Conn).writeRecord(0xc20832fb80, 0xc2082da516, 0xc2082da510,
0x8b, 0x8b, 0x0, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:748 +0x4ed
crypto/tls.(*Conn).clientHandshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/handshake_client.go:139
+0x10f9
crypto/tls.(*Conn).Handshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:977 +0xf1
net/http.func·022()
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:637 +0x3c
created by net/http.(*Transport).dialConn
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:642 +0x88c
Is it possible to catch ALL panics?

P.S.: inside my http handler method my app makes request to https:// URLs.
Lot of them. I think, thats why I see errors in tls. I think these errors
caused by network issues.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
'Paul Borman' via golang-nuts
2015-07-30 17:14:55 UTC
Permalink
Simple answer, no. You can only catch panics in your actual goroutine. If
a new goroutine is spawned then you will not catch panics in that goroutine
(as recover is based on unwinding the stack the panic was from).
Post by u***@gmail.com
I have an API service build with http lib. I have a recover inside http
132 func execApiMethod(w http.ResponseWriter, r *http.Request) {
133 defer func() {
134 if r := recover(); r != nil {
135 server.Logger.Print("Error: ", r)
136 }
137 }()
138
139 // doing some dirty stuf
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x58 pc=0x56053d]
crypto/tls.(*Conn).writeRecord(0xc20832fb80, 0xc2082da516, 0xc2082da510,
0x8b, 0x8b, 0x0, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:748 +0x4ed
crypto/tls.(*Conn).clientHandshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/handshake_client.go:139
+0x10f9
crypto/tls.(*Conn).Handshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:977 +0xf1
net/http.func·022()
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:637 +0x3c
created by net/http.(*Transport).dialConn
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:642 +0x88c
Is it possible to catch ALL panics?
P.S.: inside my http handler method my app makes request to https://
URLs. Lot of them. I think, thats why I see errors in tls. I think these
errors caused by network issues.
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
u***@gmail.com
2015-07-30 17:26:40 UTC
Permalink
So, it is impossible to make crash defence on a high level of my service?
What can you advise me to make my app more stable?
Post by 'Paul Borman' via golang-nuts
Simple answer, no. You can only catch panics in your actual goroutine.
If a new goroutine is spawned then you will not catch panics in that
goroutine (as recover is based on unwinding the stack the panic was from).
Post by u***@gmail.com
I have an API service build with http lib. I have a recover inside http
132 func execApiMethod(w http.ResponseWriter, r *http.Request) {
133 defer func() {
134 if r := recover(); r != nil {
135 server.Logger.Print("Error: ", r)
136 }
137 }()
138
139 // doing some dirty stuf
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x58 pc=0x56053d]
crypto/tls.(*Conn).writeRecord(0xc20832fb80, 0xc2082da516, 0xc2082da510,
0x8b, 0x8b, 0x0, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:748 +0x4ed
crypto/tls.(*Conn).clientHandshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/handshake_client.go:139
+0x10f9
crypto/tls.(*Conn).Handshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:977 +0xf1
net/http.func·022()
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:637 +0x3c
created by net/http.(*Transport).dialConn
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:642 +0x88c
Is it possible to catch ALL panics?
P.S.: inside my http handler method my app makes request to https://
URLs. Lot of them. I think, thats why I see errors in tls. I think these
errors caused by network issues.
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Caleb Spare
2015-07-30 17:31:11 UTC
Permalink
Post by u***@gmail.com
What can you advise me to make my app more stable?
(1) Run your program with a process supervisor that restarts it.
(2) Write defensive, well-tested code.
(3) Don't call into libraries of dubious quality.

If you recover from any panic, then what? How do you know what state
your program is in? It could very well cause worse problems (and
probably more panics) by proceeding to execute at that point. Better
to crash and restart.

-Caleb
Post by u***@gmail.com
So, it is impossible to make crash defence on a high level of my service?
What can you advise me to make my app more stable?
Post by 'Paul Borman' via golang-nuts
Simple answer, no. You can only catch panics in your actual goroutine.
If a new goroutine is spawned then you will not catch panics in that
goroutine (as recover is based on unwinding the stack the panic was from).
Post by u***@gmail.com
I have an API service build with http lib. I have a recover inside http
Post by u***@gmail.com
132 func execApiMethod(w http.ResponseWriter, r *http.Request) {
133 defer func() {
134 if r := recover(); r != nil {
135 server.Logger.Print("Error: ", r)
136 }
137 }()
138
139 // doing some dirty stuf
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x58 pc=0x56053d]
crypto/tls.(*Conn).writeRecord(0xc20832fb80, 0xc2082da516, 0xc2082da510,
0x8b, 0x8b, 0x0, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:748 +0x4ed
crypto/tls.(*Conn).clientHandshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/handshake_client.go:139
+0x10f9
crypto/tls.(*Conn).Handshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:977 +0xf1
net/http.func·022()
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:637 +0x3c
created by net/http.(*Transport).dialConn
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:642 +0x88c
Is it possible to catch ALL panics?
P.S.: inside my http handler method my app makes request to https://
URLs. Lot of them. I think, thats why I see errors in tls. I think these
errors caused by network issues.
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
'Paul Borman' via golang-nuts
2015-07-30 17:32:33 UTC
Permalink
The glib answer to your question is "don't write software that panics" :-)
But I understand where you care coming from. I have also wanted this.
Essentially what you want is to be able to hook up a function to be called
when ever an unrecovered panic happens. This is basically a version of
atexit(). Having an atexit is strongly opposed by the Go team (and not
without reason).

You would need to catch panics outside your application (notice that it
dies irregularly) and then decide what to do. One the panic hits, all bets
are off if your program can even continue to operation. So, have a
launching service (like initd or launchd) launch your job and restart it as
necessary.

-Paul
Post by u***@gmail.com
So, it is impossible to make crash defence on a high level of my service?
What can you advise me to make my app more stable?
Post by 'Paul Borman' via golang-nuts
Simple answer, no. You can only catch panics in your actual goroutine.
If a new goroutine is spawned then you will not catch panics in that
goroutine (as recover is based on unwinding the stack the panic was from).
Post by u***@gmail.com
I have an API service build with http lib. I have a recover inside http
132 func execApiMethod(w http.ResponseWriter, r *http.Request) {
133 defer func() {
134 if r := recover(); r != nil {
135 server.Logger.Print("Error: ", r)
136 }
137 }()
138
139 // doing some dirty stuf
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x58 pc=0x56053d]
crypto/tls.(*Conn).writeRecord(0xc20832fb80, 0xc2082da516,
0xc2082da510, 0x8b, 0x8b, 0x0, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:748 +0x4ed
crypto/tls.(*Conn).clientHandshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/handshake_client.go:139
+0x10f9
crypto/tls.(*Conn).Handshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:977 +0xf1
net/http.func·022()
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:637 +0x3c
created by net/http.(*Transport).dialConn
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:642 +0x88c
Is it possible to catch ALL panics?
P.S.: inside my http handler method my app makes request to https://
URLs. Lot of them. I think, thats why I see errors in tls. I think these
errors caused by network issues.
--
You received this message because you are subscribed to the Google
Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
James Aguilar
2015-07-30 17:56:11 UTC
Permalink
Post by u***@gmail.com
I have an API service build with http lib. I have a recover inside http
132 func execApiMethod(w http.ResponseWriter, r *http.Request) {
133 defer func() {
134 if r := recover(); r != nil {
135 server.Logger.Print("Error: ", r)
136 }
137 }()
138
139 // doing some dirty stuf
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x58 pc=0x56053d]
crypto/tls.(*Conn).writeRecord(0xc20832fb80, 0xc2082da516, 0xc2082da510,
0x8b, 0x8b, 0x0, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:748 +0x4ed
crypto/tls.(*Conn).clientHandshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/handshake_client.go:139
+0x10f9
crypto/tls.(*Conn).Handshake(0xc20832fb80, 0x0, 0x0)
/home/r_wilco/.gvm/gos/go1.4.2/src/crypto/tls/conn.go:977 +0xf1
net/http.func·022()
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:637 +0x3c
created by net/http.(*Transport).dialConn
/home/r_wilco/.gvm/gos/go1.4.2/src/net/http/transport.go:642 +0x88c
Is it possible to catch ALL panics?
P.S.: inside my http handler method my app makes request to https:// URLs.
Lot of them. I think, thats why I see errors in tls. I think these errors
caused by network issues.
A panic shouldn't be caused by a network issue. If it is, that's probably a
bug in go 1.4.2. More likely there's a bug in your code. In this case, my
guess is some kind of illegal concurrent modification of Conn.

It's hard to know exactly what's happening here without more info. You have
the src there on your machine. Consider logging the parameters before that
line
<https://github.com/golang/go/blob/release-branch.go1.4/src/crypto/tls/conn.go#L748>?
I have to think that would make the problem a little more clear.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Konstantin Khomoutov
2015-07-30 18:52:08 UTC
Permalink
On Thu, 30 Jul 2015 10:11:54 -0700 (PDT)
Post by u***@gmail.com
I have an API service build with http lib. I have a recover inside
[...]

I think it worth underlining the key idea of what others have already
said here: when an uncaught panic occurs, the state of your program is
undefined.

Like many (most?) of ours, you are supposedly coming from a programming
language which makes heavy use of exceptions (Java, C++, C# and so on),
and the problem with these languages is that they actually abuse
exceptions to report trivial problems or non-problems -- say, why on
Earth a failure to open a file is an exception?

Notice that while programming in these languages, programmers in most
cases take the most clear-cut approach to "handling" them: by
installing some "top-level" handler which nicely displays an error
message, may be accompanied with a stack trace. Server software might
tear processing of the current client's request down, log the error and
continue working. This "exception-happy" approach is bad because
there's no easy way to differentiate between "real" exceptions -- like
unexpectedly receiving a null pointer/reference and "non-exceptions"
which usually indicate sloppy coding when programmers doesn't bother
with trapping errors at places they should and let them propagate.

Go takes an opposing stance on this subject and reserves panics for
truly exceptional cases while processing of normal errors happens
naturally as they occur. This marks a subtle but important difference
from "exception-happy" languages: in Go, if you find yourself with an
uncaught panic on your hands, you should know that all bets are off and
the best you can do is to log the stacks of all the active goroutines
and quit. Dereferencing a nil pointer means something is really hosed
in the program, and you can't sensibly continue serving the requests.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
James Aguilar
2015-07-30 20:29:08 UTC
Permalink
To be fair to the person asking the question, this is one of the sanctioned uses of recover per https://golang.org/doc/effective_go.html#recover. It just seems like that use is not practically implementable if a library might panic in another goroutine. Which any might due to a bug or due to misuse. It's hard to suggest that the poster use better libraries, considering the one that is panicking is the distribution's crypto library.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
James Aguilar
2015-07-30 20:30:58 UTC
Permalink
Useful though this pattern is, it should be used only within a package. Parse turns its internal panic calls into error values; it does not expose panics to its client. That is a good rule to follow.
One should not expect to be able to catch panics raised in other packages.
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Giulio Iotti
2015-07-30 20:56:07 UTC
Permalink
Post by James Aguilar
To be fair to the person asking the question, this is one of the
sanctioned uses of recover per
https://golang.org/doc/effective_go.html#recover. It just seems like that
use is not practically implementable if a library might panic in another
goroutine. Which any might due to a bug or due to misuse. It's hard to
suggest that the poster use better libraries, considering the one that is
panicking is the distribution's crypto library.
In fact it would be very nice to get more info on the panic to solve it,
rather than trying to catch it at runtime.

How are the requests created? Mind to share some more code?
--
Giulio Iotti
https://twitter.com/dullboy
--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+***@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Continue reading on narkive:
Loading...