hubertlepicki
So I kind of knew of this behavior and I stumbled upon it before but actually I am not sure what is the best way to solve / debug the issue.
So on production I am observing on occasion requests that are being sent to our system, and I can see the initial Logger line for the request as being handled by the app:
12:59:19.614 request_id=Fnc9RXabbAmFCZ0AAAdG [info] GET /
but for these requests I am missing the log entry that a response was sent, i.e. no line like:
12:59:19.624 request_id=Fnc9RXabbAmFCZ0AAAdG Sent 200 in 10ms
As far as I understand, this means the Cowboy handler process exitted before it’s registered “before_send” callback is executed, which is being installed here by Plug.Logger:
https://github.com/elixir-plug/plug/blob/v1.11.1/lib/plug/logger.ex#L35
So, I have stumbled upon the situation that my requests fail, process exits, and I have no entry in logs, nor in AppSignal (we use Appsignal.Plug) as it’s just handling throws and exceptions, but not exits.
Since Cowboy is built not on OTP primitives, we don’t see the usual crash reports for these processes either. They seem to silently fail.
Now, I need to debug and fix the issue but also monitor for this not happening in the future. So I have several questions:
-
Am I missing something that on Cowboy / Plug / Phoenix level would detect, log and report these mysterious exits? I think the answer is “no” and that situation is simply not handled by the above.
-
The implementation should be as per this blog post (of mine) from 2 years ago, i.e. start a monitoring process for each request handler in a plug and log / report exits or is there some ready to use piece of infrastructure / library I should be using instead? When web requests fail in Elixir and Phoenix | AmberBit Sp. z o. o.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #iex
- #graphql
- #ai
- #genstage
- #elixirconf-us
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex










Showing Posts 1 to 10- Show Best Posts
- Show All Posts (oldest first)
- Show All Posts (newest first)
al2o3cr
What’s the log level set to in production? IIRC the “unexpected exit” reports are written at
info.axelson
Hmm, seems like a potentially similar issue to this recent (unresolved) post: Phoenix didn't handle some http requests
josevalim
Most likely the request process crashed due to a link. Cowboy should report those, unless the exit reason is shutdown, which doesn’t log anything throughout OTP.
Given you know the request path, see if that path is starting or communicating with any process that might exit.
hubertlepicki
So what is happening is when a linked process crashes (as in throws an exception) I am getting crash reports properly:
When a linked process exits, however, like this:
I only get the initla
Plug.Loggerline and then nothing, and the browser keeps spinning and loads this error:Note: the exit reason can be anything, not just
:normal, and Cowboy won’t report anything for me.Similarly to zhangzhen 's problem, this is happening on prod when I handle webhooks (although from different system) and we did have issues that for example the JSON they were sending us didn’t comply with standard. I suspect there’s a similar issue here, that the machine-generated payload somehow is messed up and some linked process (or the process of handler) performs exit() ? rather than a crash.
My plan is, as I know the path that this is happening on, is to install a monitor from within a custom plug, and collect the exit reasons from requests on that path and maybe this will give me some idea what’s going on behind the scenes.
It’s a separate question if Cowboy / Plug / Phoenix should handle the situation more gracefully. In Cowboy’s documentation there are some hints that you want to monitor handler processes, like this one from here https://ninenines.eu/docs/en/cowboy/2.6/guide/handlers/:
but I understand that monitoring all handlers would have some performance punishment.
josevalim
Can you try with something other than kill? That’s the “strongest” exit signal someone can submit and therefore we can’t generalize it.
Note this is not related to handlers though. Who is reporting this from Cowboy’s side is the connection, not the handler. And given Cowboy is already monitoring the handler process, I don’t see why it wouldn’t report other reasons too.
josevalim
I have investigated this a bit, the issue is here:
https://github.com/ninenines/cowboy/blob/master/src/cowboy_stream_h.erl#L127-L141
Cowboy is not handling a
{'EXIT', Pid, Whatever}, which is the format of exit reasons from linked processes. I would open up an issue on Cowboy and ask if they would consider adding a catch clause.hubertlepicki
Oh, I did assume they don’t intend to handle it but looking at the code it is more likely an unintended bug. I will report to them.
hubertlepicki
Actually I looked at the code more in details in Cowboy and it looks like they have the try/catch clause and this is the only way they are catching these exits.
So I think it is meant to catch exits coming from the process itself (i.,e. using
exit("SOMETHING")in Elixir), but if some other process sends it an exit signal (i.e. if usingProcess.exit(pid, "SOMETHING")thisi s not being caught unless process is trapping exits, but even then the:killwouldn’t be captured I believe.So it’s not as simple as adding clause here as it won’t be caught by try/catch clause. The only way to detect this situation I think is to monitor the process that is being sent an exit signal.
I will open an issue on Cowboy but I doubt this is something they want to handle. We’ll see.
josevalim
This is not correct.
cowboy_httpis handling exits and the code I linked above is the result of receiving a{'EXIT', PID, Reason):https://github.com/ninenines/cowboy/blob/master/src/cowboy_http.erl#L258-L260
hubertlepicki
Yes, verified that, you are correct. It only won’t catch :kill I think.