Summary
Third-party apps have no way to observe memory pressure, and running out of physical memory is an uncatchable process kill. Together these make large-allocation workloads (image/PDF decoding, crypto) impossible to make robust: an app cannot check headroom before a big operation, cannot degrade gracefully, and cannot even report a useful error — it just dies with the crash screen.
Concretely:
GetSystemStats(FreeMemory / IsSystemLowOnMemory) is denied to third-party apps — the syscall exists and does exactly what's needed (mm.ram_free()), but is_permitted_by_mask() filters it for sideloaded apps. Calling it returns an error.
- Physical OOM is unsurvivable by design: heap pages are demand-backed at first touch, so exhaustion surfaces as a data-abort in the middle of an ordinary write (often inside
memclr of a fresh allocation) — no Err, no panic hook, no chance to free caches or show a message. try_reserve-style defensive coding can't help because the failure isn't at allocation time.
Why we hit this
Debugging a real crash (a third-party image viewer OOM-killed decoding a 6000×6000 JPEG on a 128 MB device — root cause turned out to be unbounded worker queues in a decoder crate, image-rs/jpeg-decoder#290) required building a dedicated diagnostic app that measures free RAM by mapping and touching 1 MB chunks until the probe itself is OOM-killed, reading the answer off the last painted frame. That worked (~59 MB free on our unit, stable across runs — page reclamation on process exit looks solid, for the record), but it's a destructive measurement no shipping app could ever do.
Ask
Any of these would help, in rough order of value:
- Permit
GetSystemStats(FreeMemory) and IsSystemLowOnMemory in the third-party syscall mask. They're read-only and coarse; if a side channel is a concern, rounding FreeMemory (e.g. to 1 MB) would preserve the use case: "is there room for this decode?"
- A memory-pressure signal apps can subscribe to (the
SystemEventHandler plumbing looks like a natural fit), so caches can be dropped before the kill.
- Longer-term: some way for an app to learn that a specific allocation cannot be backed — e.g. an opt-in "reserve = commit" mapping mode that fails the
MapMemory call instead of the first touch — so try_reserve semantics become real on KeyOS.
Happy to provide the diagnostic app's source or test candidate builds on hardware.
Summary
Third-party apps have no way to observe memory pressure, and running out of physical memory is an uncatchable process kill. Together these make large-allocation workloads (image/PDF decoding, crypto) impossible to make robust: an app cannot check headroom before a big operation, cannot degrade gracefully, and cannot even report a useful error — it just dies with the crash screen.
Concretely:
GetSystemStats(FreeMemory / IsSystemLowOnMemory)is denied to third-party apps — the syscall exists and does exactly what's needed (mm.ram_free()), butis_permitted_by_mask()filters it for sideloaded apps. Calling it returns an error.memclrof a fresh allocation) — noErr, no panic hook, no chance to free caches or show a message.try_reserve-style defensive coding can't help because the failure isn't at allocation time.Why we hit this
Debugging a real crash (a third-party image viewer OOM-killed decoding a 6000×6000 JPEG on a 128 MB device — root cause turned out to be unbounded worker queues in a decoder crate, image-rs/jpeg-decoder#290) required building a dedicated diagnostic app that measures free RAM by mapping and touching 1 MB chunks until the probe itself is OOM-killed, reading the answer off the last painted frame. That worked (~59 MB free on our unit, stable across runs — page reclamation on process exit looks solid, for the record), but it's a destructive measurement no shipping app could ever do.
Ask
Any of these would help, in rough order of value:
GetSystemStats(FreeMemory)andIsSystemLowOnMemoryin the third-party syscall mask. They're read-only and coarse; if a side channel is a concern, rounding FreeMemory (e.g. to 1 MB) would preserve the use case: "is there room for this decode?"SystemEventHandlerplumbing looks like a natural fit), so caches can be dropped before the kill.MapMemorycall instead of the first touch — sotry_reservesemantics become real on KeyOS.Happy to provide the diagnostic app's source or test candidate builds on hardware.