Skip to content

Android: hwuiTask SIGABRT (FORTIFY destroyed-mutex) shortly after first JS callback fires #1160

@proggeramlug

Description

@proggeramlug

Summary

After the build/JNI fixes in #1159, a Perry-targeted Android app boots
cleanly through nativeMain, builds the NavStack tree, attaches the
root to the Activity, and starts the 8 ms timer pump. ~140 ms in,
within 1 ms of the first JS callback firing, an HWUI worker thread
aborts with a bionic FORTIFY check:

F libc    : FORTIFY: pthread_mutex_lock called on a destroyed mutex (0x...)
F libc    : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid N (hwuiTask1), pid M

The abort path skips debuggerd — no /data/tombstones/tombstone_*
file is written and the system data_app_native_crash dropbox tag
captures nothing. No Java exception, no JNI message in -b crash.

Timeline from logcat

… add_child:… (full NavStack tree built)
PerryApp: app_set_body: root_handle=1
PerryApp: app_run: called
PerryApp: attach_root_to_activity: setContentView called
PerryApp: start_timer_pump: setting up 8ms pump
PerryPump: nativePumpTick count=0..3
PerryCallback: invoke0: key=52 ptr=0x…
F libc   : FORTIFY: pthread_mutex_lock called on a destroyed mutex
F libc   : Fatal signal 6 (SIGABRT) in tid … (hwuiTask1)

The crash is consistent across launches (same callback key, same
thread).

Environment

Hypotheses

The fortify check fires when pthread_mutex_lock is called on memory
that was already cleared by pthread_mutex_destroy. Most likely a
sync primitive in a Drawable / Widget state struct whose backing got
freed while HWUI still had a draw scheduled against it. The 1 ms gap
between the JS callback dispatch and the abort is suggestive of a
view-invalidation path that races a destruction.

Repro

  1. Apply fix(android): unblock build + JNI bridge for the default Android target #1159.
  2. Build any non-trivial Perry app for --target android (e.g. a
    NavStack with ≥1 reactive screen).
  3. assembleDebug, install, launch.
  4. Watch the log buffer with adb logcat -b crash -d.

Diagnostic notes

  • RUST_BACKTRACE=full via devicectl --environment-variables is not
    available on adb directly; tried setprop — Android filters the
    app's stderr.
  • No tombstone path: FORTIFY aborts via __fortify_fatalabort()
    without libdebuggerd_client, so we lose backtrace.
  • Next step is probably lldb-server + remote attach, or building
    perry-ui-android under ASAN to identify the dangling mutex.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions