jaimeiniesta
Rescuing from an Erlang error
Hello, I’ve tried 2 libraries for parsing XML: sweet_xml and quinn, and both rely on the Erlang package xmerl.
They both work great, but when they encounter malformed XML, they error and exit like this:
iex(4)> Quinn.parse "<xml>"
** (exit) {:fatal, {:unexpected_end, {:file, :file_name_unknown}, {:line, 1}, {:col, 6}}}
16:21:51.714 [error] 4108- fatal: :unexpected_end
xmerl_scan.erl:4111: :xmerl_scan.fatal/2
xmerl_scan.erl:572: :xmerl_scan.scan_document/2
xmerl_scan.erl:288: :xmerl_scan.string/2
lib/xml_parser/xml_parser.ex:5: Quinn.XmlParser.parse/1
If I directly use :xmerl_scan.string/1 I get the same error:
iex(1)> :xmerl_scan.string '<xml>'
** (exit) {:fatal, {:unexpected_end, {:file, :file_name_unknown}, {:line, 1}, {:col, 6}}}
16:36:46.245 [error] 4108- fatal: :unexpected_end
xmerl_scan.erl:4111: :xmerl_scan.fatal/2
xmerl_scan.erl:572: :xmerl_scan.scan_document/2
xmerl_scan.erl:288: :xmerl_scan.string/2
Now, I want to make my app rescue from this error, but I’m not being able to do this. I’ve tried this but it doesn’t work:
iex(1)> try do
...(1)> :xmerl_scan.string '<xml>'
...(1)> rescue
...(1)> RuntimeError -> "Error!"
...(1)> end
** (exit) {:fatal, {:unexpected_end, {:file, :file_name_unknown}, {:line, 1}, {:col, 6}}}
iex(1)>
16:40:20.003 [error] 4108- fatal: :unexpected_end
I suppose that it’s because it’s not a RuntimeError I’m dealing with, because it’s not from Elixir, but Erlang. I can catch the exit, however.
How can I rescue from this error?
Thanks!
Marked As Solved
OvermindDL1
Easiest thing would be just to set a new group leader for its (yours? If run in the same process, I don’t know if it is or not) process.
It should be able to be done via:
f = get_empty_group_leader() # Implement this yourself as a supervised GenServer somewhere
:elixir.group_leader(f, self()) # Or instead of self() use whatever is the PID of the xmerl process
The part you need to implement yourself of get_empty_group_leader() just use a GenServer somewhere that implements the file streaming erlang protocol (see erlang docs), or have it basically ignore everything (I think you need to send :ok back or something on a few of them though).
Also Liked
OvermindDL1
It is not ‘raising’ an error, so rescue will not handle it. It is ‘throwing’ an :exit, so you need to catch it like:
iex> try do
...> exit "I am exiting"
...> catch
...> :exit, _ -> "not really"
...> end
"not really"
And that is the only way to handle an exit in that context (without looking at xmerl itself, if it is another process then trapping exits would work too).
EDIT: Or more accurately for your use case:
iex(2)> try do
...(2)> :xmerl_scan.string '<xml>'
...(2)> catch
...(2)> :exit, e -> {:nope, e}
...(2)> end
[error] 4108- fatal: :unexpected_end
{:nope,
{:fatal,
{:unexpected_end, {:file, :file_name_unknown}, {:line, 1}, {:col, 6}}}}
alecnmk
Greetings,
Actually there is event simpler solution(s).
-
xmerl_scanhasquiet({quiet, Flag}) as one of the options. When set totruexmerl behaves and nothing get’s error-logged. Details are here: http://erlang.org/doc/man/xmerl_scan.html -
I was experiencing same issue with false error reporting as @jaimeiniesta. And that’s Elixir Logger capturing erlang’s
standard_errorand logs it with error level to configured Logger backends. See:handle_otp_reportsconfig option of the Elixir.Logger -
Solution with wrapping xmerl parsing in a separate process and setting group leader to stub GenServer didn’t work for me. But good implementation example could be found in ExUnit Capture logs/io sources: https://github.com/elixir-lang/elixir/blob/master/lib/ex_unit/lib/ex_unit/capture_io.ex
Cheers
jaimeiniesta
For the record, SweetXml allows passing options to xmerl when parsing:
SweetXml.parse(doc, quiet: true)
Popular in Questions
Other popular 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
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









