Skip to content

Commit

Permalink
Merge pull request #1540 from pguyot/w07/print-oom-memory-info
Browse files Browse the repository at this point in the history
Add memory info to OOM crash logs

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
  • Loading branch information
bettio committed Feb 15, 2025
2 parents ed97478 + 9d099dd commit 18f961b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added the ability to run beams from the CLI for Generic Unix platform (it was already possible
with nodejs and emscripten)
- Added preliminary support for ESP32P4 (no networking support yet).
- Added memory info in `out_of_memory` crash logs to help developers fix memory issues.

### Fixed

Expand Down
39 changes: 35 additions & 4 deletions src/libAtomVM/opcodesswitch.h
Original file line number Diff line number Diff line change
Expand Up @@ -1352,6 +1352,8 @@ COLD_FUNC static void cp_to_mod_lbl_off(term cp, Context *ctx, Module **cp_mod,

COLD_FUNC static void dump(Context *ctx)
{
GlobalContext *glb = ctx->global;

fprintf(stderr, "CRASH \n======\n");

fprintf(stderr, "pid: ");
Expand All @@ -1377,7 +1379,7 @@ COLD_FUNC static void dump(Context *ctx)
term_display(stderr, ctx->x[1], ctx);
fprintf(stderr, "\nx[2]: ");
term_display(stderr, ctx->x[2], ctx);
fprintf(stderr, "\n\nStack \n------\n\n");
fprintf(stderr, "\n\nStack \n-----\n\n");

term *ct = ctx->e;

Expand All @@ -1402,12 +1404,12 @@ COLD_FUNC static void dump(Context *ctx)
ct++;
}

fprintf(stderr, "\n\nMailbox\n--------\n");
fprintf(stderr, "\n\nMailbox\n-------\n");
mailbox_crashdump(ctx);

fprintf(stderr, "\n\nMonitors\n--------\n");
// Lock processes table to make sure any dying process will not modify monitors
struct ListHead *processes_table = synclist_rdlock(&ctx->global->processes_table);
struct ListHead *processes_table = synclist_rdlock(&glb->processes_table);
UNUSED(processes_table);
struct ListHead *item;
LIST_FOR_EACH (item, &ctx->monitors_head) {
Expand All @@ -1425,7 +1427,36 @@ COLD_FUNC static void dump(Context *ctx)
term_display(stderr, term_from_local_process_id(ctx->process_id), ctx);
fprintf(stderr, "\n");
}
synclist_unlock(&ctx->global->processes_table);
synclist_unlock(&glb->processes_table);

// If crash is caused by out_of_memory, print more data about memory usage
if (ctx->x[0] == ERROR_ATOM && ctx->x[1] == OUT_OF_MEMORY_ATOM) {
fprintf(stderr, "\n\nContext memory info\n-------------------\n");
fprintf(stderr, "context_size = %zu\n", context_size(ctx));
fprintf(stderr, "context_avail_free_memory = %zu\n", context_avail_free_memory(ctx));
fprintf(stderr, "heap_size = %zu\n", memory_heap_youngest_size(&ctx->heap));
fprintf(stderr, "total_heap_size = %zu\n", memory_heap_memory_size(&ctx->heap));
fprintf(stderr, "stack_size = %zu\n", context_stack_size(ctx));
fprintf(stderr, "message_queue_len = %zu\n", context_message_queue_len(ctx));
fprintf(stderr, "\n\nGlobal memory info\n------------------\n");

processes_table = synclist_rdlock(&glb->processes_table);
size_t process_count = 0;
size_t ports_count = 0;
LIST_FOR_EACH (item, processes_table) {
Context *p = GET_LIST_ENTRY(item, Context, processes_table_head);
process_count++;
if (p->native_handler) {
ports_count++;
}
}
synclist_unlock(&glb->processes_table);

fprintf(stderr, "process_count = %zu\n", process_count);
fprintf(stderr, "ports_count = %zu\n", ports_count);
fprintf(stderr, "atoms_count = %d\n", atom_table_count(glb->atom_table));
fprintf(stderr, "refc_binary_total_size = %zu\n", refc_binary_total_size(ctx));
}
fprintf(stderr, "\n\n**End Of Crash Report**\n");
}

Expand Down

0 comments on commit 18f961b

Please sign in to comment.