-
-
Notifications
You must be signed in to change notification settings - Fork 132
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
Address ECONNRESET in issue #118 #165
base: master
Are you sure you want to change the base?
Conversation
…to run cram tests; add a cram test for aantron#118; propose a small fix for aantron#118
dream.opam
Outdated
@@ -55,6 +55,7 @@ depends: [ | |||
"conf-libev" {os != "win32"} | |||
"cstruct" {>= "6.0.0"} | |||
"dune" {>= "2.7.0"} # --instrument-with. | |||
"emile" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK Dream should not depend on emile
at all. What is your setup in some more detail, and what did you observe that caused adding emile
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generally use esy to build ocaml projects, almost as a force of habit. I believe I was building "everything", including tests, examples, etc. and esy was complaining about emile
. I went back with a new switch and ran the opam install --deps-only ./dream.opam --with-test
which worked. I will pull back this dependency from the PR.
dream.opam
Outdated
@@ -64,9 +65,12 @@ depends: [ | |||
"lwt_ssl" | |||
"logs" {>= "0.5.0"} | |||
"magic-mime" | |||
"mimic" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved to dream-mirage.opam
, which does seem to depend directly on mimic
(and the dependency is not listed). Does this work with your setup if it is moved?
dream.opam
Outdated
"mirage-clock" | ||
"mirage-crypto" {>= "0.8.1"} # AES-256-GCM. | ||
"mirage-crypto-rng" {>= "0.8.0"} # Signature of initialize. | ||
"mirage-time" | ||
"mirage-stack" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These should probably also be moved to dream-mirage.opam
.
src/http/error_handler.ml
Outdated
backtrace |> Dream__middleware.Log.iter_backtrace (fun line -> | ||
select_log error.severity (fun log -> | ||
log ?request:error.request "%s" line)) | ||
(* TODO is this the right place to handle lower level connection resets? *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not yet sure where this should be handled. Going to discuss a bit in #118, and do some research.
@@ -0,0 +1,2 @@ | |||
(cram |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than a cram test, could this be done using an in-process expect test? It seems like that approach would be more portable, as it wouldn't depend on Unix commands, and could be a bit less awkward, since it wouldn't require any complex shell command lines (everything would be kept in OCaml code).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spent some time today on this, I wanted to report back and see if you have any thoughts on a different approach.
Short answer is that it is possible, but without modifying Dream itself to add test hooks into the http module, quite ugly.
I have a successful expect test which does 3 things:
- Spins up a server on an open port using
Dream.serve
with astop
promise. - Continually runs a "reset client" which tries to connect to the server. If it connects, it immediately closes the socket
fd
which causes an RST packet to be sent to the server. It then resolves thestop
promise. - Those two promises race against a third timeout promise - if the "reset client" doesn't resolve the
stop
promise in 4 seconds, the whole thing gets torn down.
A few things I don't like:
- The test has to ignore
SIGPIPE
since closing thefd
the way it does signals a closed pipe. - There is a timer since there's a potential the server can get stuck due to other failures, causing the test to stall indefinitely.
- Since the server actually binds to an open TCP port, and we don't know when that binding succeeds, there's retry logic in the "reset client." This is kind of painful.
Reviewing the expect tests got me thinking: how useful would it be to offer a test capability to be able to inject errors at various points in Dream's request processing cycle to validate their behaviors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how useful would it be to offer a test capability to be able to inject errors at various points in Dream's request processing cycle to validate their behaviors?
Potentially very useful. I have a big project/roadmap category for making Dream apps (and probably Dream itself) really testable. But it's in the queue behind several other things.
I think it's fine then to use a cram test. If really good programmatic Dream testing materializes, I can change the test to use that later, if necessary.
src/http/error_handler.ml
Outdated
(* TODO is this the right place to handle lower level connection resets? *) | ||
| `Exn (Unix.Unix_error (Unix.ECONNRESET, _, _)) -> | ||
let condition = `String "Connection Reset at Client" in | ||
let severity = `Info in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hannesm Would it be fine for your use case if the errors were reported as warnings, as already done for most other client errors?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure. at the same time with an operations view, I'd expect if warning and error level occur, I should check the log and look how to fix the issues. OTOH if a random client resets the TCP connection or sends a malformed request, that should be on the informational level. but eventually that should be discussed in a different issue and applied uniformally.
ce104e4
to
a9a9dfc
Compare
Summary
I took a few liberties here, so please feel free to recommend alternate strategies for any of the following:
dune-project
. I felt that cram tests would be the best way to make the TCP RST packet issue pop up. I generally like how this turned out, however I don't really like how it does open TCP port selection.dream.opam
file, such asemile
andmimic
. I personally run Dream's build in an esy "harness" of sorts, and it was not happy about those undeclared dependencies. Not a major issue to remove if this adds too much clutter or is undesired.What has been done?
`Info