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

context deadline can cause surprising errors #4196

Closed
jhump opened this issue Dec 11, 2023 · 4 comments
Closed

context deadline can cause surprising errors #4196

jhump opened this issue Dec 11, 2023 · 4 comments

Comments

@jhump
Copy link

jhump commented Dec 11, 2023

When a context deadline is added to the context of an *http.Request and the deadline elapses, the actual errors returned from this package can be a bit surprising. In particular, most context-deadline-checking code really would like to test errors using something like errors.Is(err, context.DeadlineExceed) to ascertain if the error is due to the context deadline.

However, that formulation returns false for both quic.IdleTimeoutError and quic.HandshakeTimeoutError. Ideally, both of these error types would return true for this formulation via their implementation of an Is(error) method. That is how the core runtime's net.timeoutError works: https://github.com/golang/go/blob/master/src/net/net.go#L600-L60. Both these types already have an Is(error) method, but they only handle formulations like errors.Is(err, net.ErrClosed) (link).

This is very similar to golang/go#64449

@jhump
Copy link
Author

jhump commented Dec 11, 2023

It looks like my particular issue may be a little different than described. I was definitely seeing "timeout: no recent network activity" in my logs, which is why I thought quic.IdleTimeoutError may be to blame.

However, it looks like the actual error that a client is much more likely to receive is an http3.Error with a code of H3_REQUEST_CANCELLED. With quic.IdleTimeoutError, my work-around was check for instances of net.Error where err.Timeout() returned true. But with this latest observation, I must put work-around code that is quite bespoke to this library to properly detect context-related errors. I suspect an appropriate improvement would not involve touching http3.Error but instead something else in the round-tripper so that it can correctly return context.Canceled or context.DeadlineExceeded when an http3.Error is triggered via the context.

@marten-seemann
Copy link
Member

I'm not sure I understand under which condition exactly you expect the context cancelation error.

In general, an idle timeout can occur at any time during the handshake or the connection, if the other peer suddenly goes away without telling us. There's no context being canceled here, so we shouldn't return a context cancelation error.

Am I right to assume that you're setting the context on the http.Request, cancel that context, and now expect the error on RoundTripper.RoundTrip to be a context cancelation error? Is that what HTTP/2 does? Assuming that's the case, I agree that this would be the correct behavior, and we should make sure that HTTP/3 does the same (I haven't checked what it does right now).

@jhump
Copy link
Author

jhump commented Dec 12, 2023

Am I right to assume that you're setting the context on the http.Request, cancel that context, and now expect the error on RoundTripper.RoundTrip to be a context cancelation error?

Yes. That is what the standard lib net/http stuff does, with the exception of the bug I linked above, where the dial operation (when no existing connection is in the pool) can instead return os. ErrDeadlineExceeded.

For the case of the error I'm seeing, I think the HTTP/3 round tripper implementation could examine the http.Error and the request's context and then massage the error to wrap the error and return something that is easier to inspect.

@marten-seemann
Copy link
Member

Closing in favor of #4205.

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

No branches or pull requests

2 participants