-
Notifications
You must be signed in to change notification settings - Fork 106
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
Weird crash (Unknown term type: 100) #1346
Comments
this code is weird:
I suggest:
underlying error I assume to be that you are receiving a bitstring, and not a binary, which is why I assume :erlang.error is crashing.. (I believe bitstring support is not complete #154) |
Is it? In my understanding, I don't think I tried the @impl :gen_server
def handle_cast({:append, new}, %State{buffer: [latest | rest]} = state) when is_binary(new) and is_binary(latest) do
...
If |
You are probably right, not familiar with erlang:error, and never seen this coding style in elixir land. But think it's needs investigation if a codepath that is never called is crashing.. I'm thinking OOM then maybe? but could be anything, there seems to a very tight loop reading uart.. |
Me either. I seldom use raise/throw system on Elixir. The code above is just for debugging. The reason why I use
|
I am still somewhat a novice to the BEAM, and especially Elixir, but I believe this line is incorrect. Shouldn't you be matching against Please feel free to take this with a grain of salt, I may be entirely incorrect here. I frequently get confused by subtle differences between Erlang and Elixir ;-) |
@UncleGrumpy strings in Elixir (as in literals between ") are Erlang binaries. Erlang strings (as in lists of integers) are represented with single quotes or with a sigil. |
@pguyot thanks. I need a poster sized cheat sheet of all those common differences to hang on the wall beside me 😂 |
I got some additional results. Let me describe the problem again. This code crashes with abort and the message def handle_cast({:append, new}, state) when is_binary(new) do
%State{buffer: [latest | rest]} = state
{current, next} =
case :binary.split(new, "\r\n") do
[unfinished_line] -> {unfinished_line, nil}
[line, ""] -> {line <> "\r\n", nil}
[line, rest] -> {line <> "\r\n", rest}
end
if(!is_binary(latest), do: :erlang.error({:latest, latest, state}))
...
end crash report
Besides this code just raises def handle_cast({:append, new}, state) when is_binary(new) do
%State{buffer: [latest | rest]} = state
if(!is_binary(latest), do: :erlang.error({:latest, latest, state}))
{current, next} =
case :binary.split(new, "\r\n") do
[unfinished_line] -> {unfinished_line, nil}
[line, ""] -> {line <> "\r\n", nil}
[line, rest] -> {line <> "\r\n", rest}
end
# commented out
# if(!is_binary(latest), do: :erlang.error({:latest, latest, state}))
...
end crash report
So it's really weird but that Btw, There seems no chance that defp loop(pid, port) do
{:ok, read} = :uart.read(port)
if(!is_binary(read), do: :erlang.error({:read, read}))
:gen_server.cast(pid, {:append, read})
loop(pid, port)
end |
Could you please confirm which version of AtomVM you are using? This is a bug in the VM indeed, some lack of support of encoded terms that are generated by Elixir. I did fix a similar issue recently. |
I'm using forked version of AtomVM (https://github.com/realglobe-Inc/AtomVM/ at f796f0d), which is based on |
Rebuilt the VM v0.6.5 and tried again now. The issue with Boot up log, which includes the VM version
|
Thank you. Would you mind sharing a minimal example or maybe your .avm? |
I'm sorry that I cannot provide the whole avm file because part of the logic is related to our business. I'm trying to make a minimal reproductive code for the issue, but I'm keep failing. Is there a good way to dump the term in problem so that I can make a simple code to reproduce the issue? I tried |
What you describe looks more and more like a memory corruption issue, which may or may not be related to uart. |
Hmm I tried |
esp32 uart_driver seems a little bit broken indeed, especially with multicore (such as S3). Data may arrive through interrupts as well as through calls to read. Do you want to confirm the bug goes away if you set the schedulers count to 1? Erlang: erlang:system_flag(schedulers_online, 1) Elixir: :erlang.system_flag(:schedulers_online, 1) |
I tried I noticed that the following code invokes the issue as soon as they call def handle_cast({:append, new}, %State{buffer: [latest | rest]} = state) when is_binary(new) do
IO.inspect(:erlang.term_to_binary(state))
...
end I may be able to create the minimal reproductive code using this. |
I found that the following code always crashes, but I'm not sure that is related to the issue or not. It seems another unrelated issue. defmodule Entrypoint do
defmodule State do
defstruct pid: nil
end
def start() do
state = %State{pid: self()}
IO.inspect(:erlang.term_to_binary(state))
end
end
It seems that AtomVM crashes when you apply |
I tried to re-implement def handle_cast({:append, new}, %State{buffer: [latest | rest]} = state) when is_binary(new) do
{current, next} =
case split_by_crlf(new) do
[unfinished_line] -> {unfinished_line, nil}
[first_line, rest] -> {first_line, rest}
end
buffer =
case latest do
<<_::binary-size(byte_size(latest) - 2), "\r\n">> -> [current, latest | rest]
_ -> [latest <> current | rest]
end
if next == nil do
{:noreply, %State{state | buffer: buffer}}
else
handle_cast({:append, next}, %State{state | buffer: buffer})
end
end
defp find_line_end(bin, index \\ 0) do
if index + 1 < byte_size(bin) do
case [:binary.at(bin, index), :binary.at(bin, index + 1)] do
~c"\r\n" -> index + 1
_ -> find_line_end(bin, index + 1)
end
else
nil
end
end
defp split_by_crlf(bin) do
case find_line_end(bin) do
nil ->
[bin]
line_end ->
[
:binary.part(bin, 0, line_end + 1),
:binary.part(bin, line_end + 1, byte_size(bin) - line_end - 1)
]
end
end
... |
True. I created #1350 for this. It is unrelated to the error you initally reported here. |
This is possible. I have been a little bit confused by the maths of binary allocation when I last touched this bit, but I didn't think it affected |
I found that the following code often (or more than often, as it seems 100%) crashes with
unknown term type
error.Seems really weird because only
latest
is in abnormal state, butstate
, in whichlatest
exist, looks like a normal map.When it crashes, the term type number is always the same (100).
I tried to move
if(!is_binary(latest), do: :erlang.error({:latest, latest, state}))
from current position to the top of the function, then the current error disappears. Instead, I gotbadarg
error.After adding
rescue
clause, I cannot reproduce the error any more. I don't know why at all.Actually, I found the
badarg
error at first. Trying hard to find out what causes the error, I found that therescue
clause clears the error. I tried more to find out why it removes the error, I happened to findbug: found unknown term type: 0x64
.Sorry that I cannot show all the project because the code includes some confidential information.
The
handle_cast
function above receives every message from modem via UART. Sometimes it is called extremely frequently.The text was updated successfully, but these errors were encountered: