Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/http: TimeoutHandler hides panic after timeout #34608

Open
pam4 opened this issue Sep 30, 2019 · 3 comments
Open

net/http: TimeoutHandler hides panic after timeout #34608

pam4 opened this issue Sep 30, 2019 · 3 comments
Milestone

Comments

@pam4
Copy link

@pam4 pam4 commented Sep 30, 2019

If TimeoutHandler's inner handler panics after the timeout, the panic is discarded:
https://play.golang.org/p/GT7lVCBu163

This happens because after the timeout, TimeoutHandler.ServeHTTP doesn't wait for the inner handler to complete, and anything on panicChan is lost.
I understand that waiting for the inner handler would partly defeat the purpose of TimeoutHandler. If waiting is not acceptable, perhaps the docs should warn about dropped panics.

Also, timeoutWriter.Push panics if called after the timeout:
https://play.golang.org/p/-AZj5t-ViyJ
(Not sure if this should be a separate issue.)

This happens because timeoutWriter.Push may call the underlying Push after or concurrently with the completion of TimeoutHandler.ServeHTTP (after which http2responseWriter.rws is set to nil).
Of course the panic is not logged for the reason already mentioned.

@bcmills bcmills added this to the Go1.14 milestone Sep 30, 2019
@bcmills
Copy link
Member

@bcmills bcmills commented Sep 30, 2019

@cuonglm
Copy link
Contributor

@cuonglm cuonglm commented Sep 30, 2019

I think adding document for dropping panic seems ok. But Push panics after timeout reached is not an issue at all. We can easily adding a check but it's not worth and meaningless.

@pam4
Copy link
Author

@pam4 pam4 commented Oct 2, 2019

The docs clearly state:

A ResponseWriter may not be used after the Handler.ServeHTTP method has returned.

Any caller of ServeHTTP takes this rule for granted and may break in unexpected ways if it's not respected (for http2responseWriter, it leads to dereferencing a pointer that is concurrently set to nil).

Calling the Push overlay after timeout is nothing abnormal, in fact there's no way to make sure it won't happen.
It should be safe to use the overlay ResponseWriter for as long as the corresponding handler is running, OTOH the underlying one has a different lifespan and is TimeoutHandler's responsibility.

Concurrency aside, panic equals interrupted goroutine (I fail to see how it doesn't make a big difference in a non-fatal condition), but in this case it's worse because no clue is left behind! (No logs, see first part of the issue.)

There's also another concurrency issue: timeoutWriter.Push calls the underlying Push while the other goroutine calls the underlying Write/WriteHeader. Even if this is safe for http2responseWriter, it may break for a custom ResponseWriter (not required to be safe for concurrent use).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.