mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-28 11:48:45 +00:00
feat(core): check that GC restores free heap memory
Enabled only for frozen debug builds. [no changelog]
This commit is contained in:
parent
a787d21b3f
commit
41db573ef9
@ -302,6 +302,31 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorutils_enable_oom_dump_obj,
|
||||
mod_trezorutils_enable_oom_dump);
|
||||
#endif // MICROPY_OOM_CALLBACK
|
||||
|
||||
/// if __debug__:
|
||||
/// def check_free_heap(previous: int) -> int:
|
||||
/// """
|
||||
/// Assert that free heap memory doesn't decrease.
|
||||
/// Returns current free heap memory (in bytes).
|
||||
/// Enabled only for frozen debug builds.
|
||||
/// """
|
||||
STATIC mp_obj_t mod_trezorutils_check_free_heap(mp_obj_t arg) {
|
||||
mp_uint_t free_heap = trezor_obj_get_uint(arg);
|
||||
#if MICROPY_MODULE_FROZEN_MPY
|
||||
gc_info_t info;
|
||||
gc_info(&info);
|
||||
if (free_heap > info.free) {
|
||||
gc_dump_info();
|
||||
mp_raise_msg_varg(&mp_type_AssertionError,
|
||||
"Free heap decreased by " UINT_FMT " bytes",
|
||||
free_heap - info.free);
|
||||
}
|
||||
free_heap = info.free; // current free heap
|
||||
#endif
|
||||
return mp_obj_new_int_from_uint(free_heap);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorutils_check_free_heap_obj,
|
||||
mod_trezorutils_check_free_heap);
|
||||
|
||||
/// if __debug__:
|
||||
/// def check_heap_fragmentation() -> None:
|
||||
/// """
|
||||
@ -559,6 +584,8 @@ STATIC const mp_rom_map_elem_t mp_module_trezorutils_globals_table[] = {
|
||||
{MP_ROM_QSTR(MP_QSTR_enable_oom_dump),
|
||||
MP_ROM_PTR(&mod_trezorutils_enable_oom_dump_obj)},
|
||||
#endif
|
||||
{MP_ROM_QSTR(MP_QSTR_check_free_heap),
|
||||
MP_ROM_PTR(&mod_trezorutils_check_free_heap_obj)},
|
||||
{MP_ROM_QSTR(MP_QSTR_check_heap_fragmentation),
|
||||
MP_ROM_PTR(&mod_trezorutils_check_heap_fragmentation_obj)},
|
||||
#endif
|
||||
|
@ -104,6 +104,13 @@ if __debug__:
|
||||
"""
|
||||
Dump GC info in case of an OOM.
|
||||
"""
|
||||
if __debug__:
|
||||
def check_free_heap(previous: int) -> int:
|
||||
"""
|
||||
Assert that free heap memory doesn't decrease.
|
||||
Returns current free heap memory (in bytes).
|
||||
Enabled only for frozen debug builds.
|
||||
"""
|
||||
if __debug__:
|
||||
def check_heap_fragmentation() -> None:
|
||||
"""
|
||||
|
@ -36,11 +36,8 @@ import trezor.pin # noqa: F401
|
||||
# usb imports trezor.utils and trezor.io which is a C module
|
||||
import usb
|
||||
|
||||
# create an unimport manager that will be reused in the main loop
|
||||
unimport_manager = utils.unimport()
|
||||
|
||||
# unlock the device, unload the boot module afterwards
|
||||
with unimport_manager:
|
||||
with utils.unimport():
|
||||
import boot
|
||||
del boot
|
||||
|
||||
@ -63,6 +60,7 @@ if utils.USE_BLE:
|
||||
|
||||
|
||||
# run the endless loop
|
||||
unimport_manager = utils.unimport()
|
||||
while True:
|
||||
with unimport_manager:
|
||||
import session # noqa: F401
|
||||
|
@ -37,7 +37,7 @@ from trezorutils import ( # noqa: F401
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if __debug__:
|
||||
from trezorutils import LOG_STACK_USAGE, check_heap_fragmentation
|
||||
from trezorutils import LOG_STACK_USAGE, check_free_heap, check_heap_fragmentation
|
||||
|
||||
if LOG_STACK_USAGE:
|
||||
from trezorutils import estimate_unused_stack, zero_unused_stack # noqa: F401
|
||||
@ -94,17 +94,22 @@ def unimport_end(mods: set[str], collect: bool = True) -> None:
|
||||
class unimport:
|
||||
def __init__(self) -> None:
|
||||
self.mods: set[str] | None = None
|
||||
if __debug__:
|
||||
self.free_heap = 0
|
||||
|
||||
def __enter__(self) -> None:
|
||||
self.mods = unimport_begin()
|
||||
|
||||
def __exit__(self, _exc_type: Any, _exc_value: Any, _tb: Any) -> None:
|
||||
def __exit__(self, exc_type: Any, _exc_value: Any, _tb: Any) -> None:
|
||||
assert self.mods is not None
|
||||
unimport_end(self.mods, collect=False)
|
||||
self.mods.clear()
|
||||
self.mods = None
|
||||
gc.collect()
|
||||
|
||||
if __debug__ and exc_type is not SystemExit:
|
||||
self.free_heap = check_free_heap(self.free_heap)
|
||||
|
||||
|
||||
def presize_module(modname: str, size: int) -> None:
|
||||
"""Ensure the module's dict is preallocated to an expected size.
|
||||
|
Loading…
Reference in New Issue
Block a user