Repository navigation
stacktrace: Don't allocate module paths when no frame has a line - #2436
Conversation
petermm
left a comment
There was a problem hiding this comment.
nice find!
just a small nit:
Review: AtomVM PR #2436
PR: #2436
Title: stacktrace: Don't allocate module paths when no frame has a line
Reviewed head: aa78fe16abd5204e3c86a554196ee4c86962ca83
Base: 18b35870a0be75c42892db9a0762e8c7a7d61323
Summary
The allocation fix looks correct: when there are no source locations, no module-path entries are needed. Keeping module_paths as NULL avoids treating a permitted malloc(0) result as an allocation failure; cleanup via free(NULL) is valid. Positive-sized allocation failure retains its previous behavior.
One actionable test-configuration issue should be fixed. No additional correctness issues were found in the runtime change or the test packaging.
Findings
[P2] Register the stacktrace test only when stacktraces are enabled
Location: src/platforms/esp32/test/main/test_main.c, lines 382–386
The new test is registered unconditionally, but the test project's new AVM_CREATE_STACKTRACES CMake option still permits an explicit OFF. With -DAVM_CREATE_STACKTRACES=OFF, stacktrace_build() intentionally returns UNDEFINED_ATOM, and the Erlang test returns {not_a_list, undefined}. The C assertion then fails despite the VM behaving correctly for that configuration.
The default ON does not prevent this: CMake's option() preserves an explicit cache value. The host test suite already accounts for this configuration through SKIP_STACKTRACES in tests/test.c.
Suggested fix: Guard registration with the same feature definition that selects the implementation. libAtomVM exports AVM_CREATE_STACKTRACES as a public compile definition when enabled. The BEAM can remain compiled and packaged unconditionally.
diff --git a/src/platforms/esp32/test/main/test_main.c b/src/platforms/esp32/test/main/test_main.c
--- a/src/platforms/esp32/test/main/test_main.c
+++ b/src/platforms/esp32/test/main/test_main.c
@@ -379,12 +379,14 @@ TEST_CASE("test_list_to_atom", "[test_run]")
TEST_ASSERT(ret_value == OK_ATOM);
}
+#ifdef AVM_CREATE_STACKTRACES
TEST_CASE("test_stacktrace", "[test_run]")
{
term ret_value = avm_test_case("test_stacktrace.beam");
TEST_ASSERT(ret_value == OK_ATOM);
}
+#endif
TEST_CASE("test_list_to_binary", "[test_run]")
{Validation after applying: Build the ESP32 test project with AVM_CREATE_STACKTRACES=ON and OFF. With ON, the new test should be registered and pass on ESP-IDF; with OFF, it should not be registered. For the regression itself, retain the no-line-info scenario on a platform where malloc(0) returns NULL, checking that it fails before the runtime fix and passes afterward.
|
Thanks! Guarded the registration with |
aa78fe1 to
7ae2f71
Compare
|
@bettio this one has @petermm's approval now (after the The red jobs are all in CI setup, not in the build or the tests: |
bettio
left a comment
There was a problem hiding this comment.
All good. Just few nitpicks.
|
By the way, if you are making changes, let's do |
stacktrace_build() allocated num_mods module path pairs, one per frame with line information, and returned the raw stacktrace when malloc failed. With no such frame num_mods is 0, and malloc(0) returns NULL on ESP-IDF, so every stacktrace of modules without line information came back raw, with "Unable to allocate space for module paths" on stderr. Allocate only when there is something to store. The ESP32 test project now creates stacktraces like the firmware build does, so test_no_line_info_stacktrace sees what a device sees. Signed-off-by: Gabriel Mancini <gabriel.mancini@gmail.com>
7ae2f71 to
69c730f
Compare
|
Thanks @bettio! Rebased on |
stacktrace_build()allocatesnum_modsmodule path pairs, one per frame location with line information, and returns the raw stacktrace whenmallocfails. When no frame has line information,num_modsis 0, and on ESP-IDFmalloc(0)returnsNULL(heap_caps_base.c), so the stacktrace comes back raw ({NumFrames, 0, 0, 0, [{ModIndex, Offset}, ...], Class}) instead of a list, and stderr shows:That covers every application packed without line information on ESP32: we saw it on all our boards (ESP32 and ESP32-S3 with 8 MB of PSRAM), never related to memory. glibc returns a non-NULL pointer for
malloc(0), which is why generic_unix never shows it.The fix allocates only when
num_mods > 0. With 0 the loop never touchesmodule_paths, andfree(NULL)is fine.Test.
test_stacktrace(ESP32) raises in a module compiled withno_line_infoand checks that the stacktrace is a list with a frame of that module. The ESP32 test project never declaredAVM_CREATE_STACKTRACES, so stacktraces wereundefinedthere; it now enables it assrc/platforms/esp32/CMakeLists.txtdoes, which is what a device runs with.{not_a_list,{2,0,0,0,[{0,25},{0,20,erlang,error,1}],error}}; with it,test_stacktracepasses (test_socketfails here as it does on plain release-0.7, no network inside QEMU).test-erlang: all pass.These changes are made under both the "Apache 2.0" and the "GNU Lesser General Public License 2.1 or later" license terms (dual license).
SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later