Environment
- Qoder Desktop 0.4.8 (stable), Linux x86_64
- Arch Linux / Omarchy 2026.9.7, kernel 7.2.8-9-omarchy, Wayland (Hyprland)
- Remote Control: enabled (Settings → Mobile)
- Chat session contains image attachments / tool-result images
- Bundled: @img/sharp 0.34.5, @img/sharp-libvips-linux-x64 1.2.4 (libvips 8.17.3)
- System GLib/libgobject 2.90.0
- Helper process:
Qoder Remote Control Sync,node.mojom.NodeService,--max-old-space-size=512
Summary
Completing an assistant turn in a chat that contains images starts the Remote Control history sync. 9–17 ms after the sync logs REMOTE_CONTROL_IMAGE_INVALID (stage resources), the Qoder Remote Control Sync utility process dies with SIGSEGV (exit code 139). The main process survives and respawns the helper, which retries — in one episode this produced 6 crashes in 24 seconds. I collected 11 coredumps over 4 episodes; every core has the same stack.
Steps to reproduce
- Enable Remote Control (Settings → Mobile).
- Open a chat session that contains image attachments.
- Complete an assistant turn (this triggers the history sync; in my case it was a long final report).
- Watch
main.log:REMOTE_CONTROL_IMAGE_INVALIDis followed 9–17 ms later by the helper crash.
Reproduced 4/4 episodes, 11 cores. reason:"killed", exitCode:15 entries in the log are normal helper shutdowns; the crashes are the exitCode:139 entries.
Expected
The sync either completes, or skips the offending image and continues. The helper process stays alive.
Actual
SIGSEGV in a libuv worker thread inside the bundled sharp/libvips addon. The helper exits with 139, gets respawned, and the retry loop can crash repeatedly. The main window stays responsive; no data was lost and there was no OOM pressure.
Log evidence (timestamps UTC; main.1.log)
[2026-10-18T18:29:55.586Z] [WARN] [main] [QoderRemoteControl] Remote Control 操作未完成 {"sessionId":"<redacted>","stage":"resources","failureCode":"REMOTE_CONTROL_IMAGE_INVALID"}
[2026-10-18T18:29:55.595Z] [ERROR] [main] [App] Electron child process exited {"type":"Utility","reason":"crashed","exitCode":139,"serviceName":"node.mojom.NodeService","name":"Qoder Remote Control Sync"}
Core dump stack (gdb, all 11 cores identical)
SIGSEGV, SEGV_MAPERR, PC = 0x0, thread = libuv-worker
#0 0x0000000000000000 (call through null)
#1 g_object_unref (system libgobject-2.0.so.0, GLib 2.90.0)
#2 sharp-linux-x64.node + 0x1835d
#3 sharp-linux-x64.node + 0x2000c
#4 sharp-linux-x64.node + 0x16eac
... node::ThreadPoolWork / libuv-worker
Analysis
Verified from the core and the shipped binaries:
- The crashing path is the image-handling (“resources”) stage of the Remote Control sync, on its error path.
sharp-linux-x64.nodehas noNEEDEDentry for libgobject but referencesg_object_unrefas an undefined symbol, so it binds at runtime to the system libgobject that Electron loads.- The bundled
libvips-cpp.so.8.17.3statically embeds GLib: it defines and exports its owng_object_unref,g_object_ref,g_malloc, etc. (1788g_*symbols), and has noNEEDEDentry for libglib/libgobject.
Inference: two independent GLib implementations coexist in the helper. A VipsImage allocated/finalized through the bundled GLib is unref’d through the system GLib (or vice versa), so the object’s class pointer is incompatible and the finalize vfunc resolves to NULL — which matches the deterministic PC = 0. Because this happens on the validation-failure path, any image the sync considers invalid can trigger it.
Secondary observation: at least one image URL that the sync reported as REMOTE_CONTROL_IMAGE_INVALID returned a valid PNG when fetched manually, so I could not confirm that the image was genuinely invalid — the validation itself may also be worth a look.
Suggested fixes
- Ensure a single GLib implementation for the image pipeline (e.g. link libvips/libgobject against the same GLib, or prevent the addon’s
g_*symbols from binding across the two copies). - Treat per-image sync failures as non-fatal: log, skip the image, keep the helper alive.
Workaround
Disabling Settings → Mobile → Remote Control stops the crashes. As of 2026-10-18 the updater reports server-no-update, so 0.4.8 is the latest offered build.
Attachments
I can provide a redacted main.log excerpt. Core dumps are not attached: they contain full process memory, including chat content.