Skip to content

[http] Remove exceptions from HTTP/1 codec callbacks#11101

Merged
jmarantz merged 6 commits intoenvoyproxy:masterfrom
asraa:remove-callback-throws
May 14, 2020
Merged

[http] Remove exceptions from HTTP/1 codec callbacks#11101
jmarantz merged 6 commits intoenvoyproxy:masterfrom
asraa:remove-callback-throws

Conversation

@asraa
Copy link
Contributor

@asraa asraa commented May 7, 2020

Commit Message: Remove exceptions from HTTP/1 codec callbacks. Replaces with http_parser exit codes that indicate failure. codec_status_ propagates the error.

Additional Description:

  • I know the diff is slightly messy but the principles I abided by were: Replace throw with setting codec_status_, immediately return and propagate return up to callback with an error exit code, always ASSERT(dispatching_) in the body of the method that throws, always ASSERT(codec_status_.ok()) before setting the codec status.
  • The remaining exception is in encodeHeaders, which I will need to replace with ENVOY_BUG
  • I audited for throws in the includes for this file and did not find anything used in the codec_impl, but I will need to do another pass.
  • This is just part 1 of my HTTP/1 PRs. Part 2 is exception to error handling for encodeHeaders and any other utility functions. This is just a PR to stage.

Testing: Tests pass, codec_impl_fuzz_test has been running for a few minutes.
Risk level: Medium, this should do nothing but is a codec behavior change.
Issues: #10878

Signed-off-by: Asra Ali asraa@google.com

Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
@asraa asraa requested a review from yanavlasov May 7, 2020 17:18
@mattklein123 mattklein123 self-assigned this May 7, 2020
@mattklein123
Copy link
Member

The remaining exception is in encodeHeaders, which I will need to replace with better error handling since the throw is not caught in a separate PR.

Just to make sure we are all on the same page, what is the plan for the "application error" exceptions? I don't really know what the caller would do with an error other than crash, and adding return code from encodeHeaders would be a larger change. Can we just PANIC/RELEASE_ASSERT in those cases for now?

@asraa
Copy link
Contributor Author

asraa commented May 7, 2020

Can we just PANIC/RELEASE_ASSERT in those cases for now?

Hmm yeah I'm happy to RELEASE_ASSERT, since that's preserving existing behavior, but I think I had some feedback to change this as I remove exceptions. Would you imagine some error status handling in sendLocalReply and other callers of encodeHeaders? @alyssawilk @antoniovicente What do you think?

@mattklein123
Copy link
Member

Would you imagine some error status handling in sendLocalReply and other callers of encodeHeaders?

I honestly don't know what that would be. If we insist in not crashing in these cases the only thing I can think of to do would be to ASSERT and then continue on to fill in some default values or something.

"envoy.reloadable_features.reject_unsupported_transfer_encodings")),
output_buffer_([&]() -> void { this->onBelowLowWatermark(); },
[&]() -> void { this->onAboveHighWatermark(); }),
dispatching_(false), output_buffer_([&]() -> void { this->onBelowLowWatermark(); },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like the global capture could have unexpected costs as the code evolves. I think it's OK for tests, but WDYT of making this prod code explicitly capture what it needs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unfamiliar with this code, but I think the reason why it was written like that was because client/server would need to capture a disjoint set of things. Could pass both active request/pending response in, I can try to

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, sorry. I misread the diff and thought you had added this. I'm not crazy about it but it's pre-existing so lgtm.

sendProtocolError(Http1ResponseCodeDetails::get().InvalidUrl);
throw CodecProtocolException("http/1.1 protocol error: invalid url in request line");
ASSERT(codec_status_.ok());
ENVOY_LOG_MISC(info, "SETTING PROTOCOL ERROR");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you plan to leave this in? If so, can you include the URL?

Copy link
Contributor Author

@asraa asraa May 8, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done -- but actually this was useful for debugging. What do you think about adding logging statements when the codec_status_ sets an error?

This ends up getting logged when onData calls dispatch, but that was too late for any codec level test debugging. At that point I might want to wrap the whole pattern of

ASSERT(codec_status_.ok());
codec_status_ = .... ;
ENVOY_LOG_MISC(trace, codec_status_.message);

into one thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When debugging something in the heat of the moment, more logs are great, as long as the quantity of logs doesn't become a problem. I only suggest that if there's a URL to log, we include that.

asraa added 2 commits May 8, 2020 09:33
Signed-off-by: Asra Ali <asraa@google.com>
Signed-off-by: Asra Ali <asraa@google.com>
@alyssawilk
Copy link
Contributor

alyssawilk commented May 11, 2020 via email

Signed-off-by: Asra Ali <asraa@google.com>
@mattklein123
Copy link
Member

Sounds like a perfect use of ENVOY_BUG (assert in debug mode, log error
with N^2 backoff in opt) with error handling - wasn't someone going to look
into that this quarter?

Yes, agreed, if there is a sane default behavior we can agree on this is a fine use case of that paradigm IMO.

mattklein123
mattklein123 previously approved these changes May 12, 2020
Copy link
Member

@mattklein123 mattklein123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks this LGTM at a high level so will defer to others for detailed review. Nice work!

Copy link
Contributor

@jmarantz jmarantz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically looks great, modulo the [&] capture and some commenting around the significance of the specific status codes ints.


bool resetStreamCalled() { return reset_stream_called_; }

// The following define special return values for http_parser callbacks.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put in the comment here where these constants come from, and maybe that they need to not overlap with standard HTTP Status codes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks -- one clarification: you said "These codes do not overlap with standard HTTP Status codes". Is it also correct to strengthen that to "These codes must not overlap with standard HTTP Status codes"? Or are they unrelated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated. They're return values for the user defined callbacks for the parser, so they don't do anything but signal execution flow for the parser.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe "The use of these codes are distinct from standard HTTP Status codes"

@jmarantz
Copy link
Contributor

/wait

Signed-off-by: Asra Ali <asraa@google.com>
@jmarantz
Copy link
Contributor

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s), but failed to run 2 pipeline(s).

@jmarantz jmarantz merged commit 3550a7a into envoyproxy:master May 14, 2020
asraa added a commit that referenced this pull request May 14, 2020
asraa added a commit to asraa/envoy that referenced this pull request May 14, 2020
…oxy#11101)"

This reverts commit 3550a7a.

Signed-off-by: Asra Ali <asraa@google.com>

Signed-off-by: asraa <asraa@google.com>
asraa added a commit to asraa/envoy that referenced this pull request May 14, 2020
…oxy#11101)"

This reverts commit 3550a7a.

Signed-off-by: Asra Ali <asraa@google.com>
asraa added a commit that referenced this pull request May 15, 2020
#11194)

This reverts commit 3550a7a.

Signed-off-by: Asra Ali <asraa@google.com>
asraa added a commit that referenced this pull request Aug 10, 2020
Commit Message:
Remove all throw statements from H/1 codec
This change removed all uses of C++ exceptions from H/1 codec. I modeled the flow after Yan's H/2 work (#11575). Codec status are set in uniform helper methods. This is the only change from the previous PR (#11101), besides merging newer exceptions.

This change replaces all throw statements with a return of corresponding error Status and adds plumbing to return the status to codec callers. The dispatch() method returns the encountered error to the caller, which will be handled accordingly.

The calls to the RequestEncoder::encodeHeaders() NOT called from dispatch() method will RELEASE_ASSERT if an error code is returned. This does not alter the existing behavior of abnormally terminating the process, just the method of termination: RELEASE_ASSERT vs uncaught exception.

Risk Level: High (Codec changes)
Signed-off-by: Asra Ali <asraa@google.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants