Diagram

IBus engine crash = desktop crash. 8 pitfalls nearly made me give up, and how cddcb40 saved the day.

This is part 2/8 of the TUX IM Dev Log: From Zero to 0.1 series.

Part 2 · The First Scream of the IBus Engine — How I Crashed the Daemon

In Part 1, I set a flag for myself: no exception should escape the engine process. But honestly, when I wrote that, I had already crashed three times. This is a retrospective — covering the bugs that tormented me between aa4b094 and cddcb40, and how cddcb40 plugged all those holes at once.

First Scream: Every Keypress Becomes Two Letters

When I first tested Pinyin input, I typed n, expecting buffer to be n, but got nn. Typed ni, got nii. Every keypress was consumed twice.

After half an hour of investigation: IBus sends each keypress twice — once as press (state=0), once as release (state=0x40000000 = IBus.ModifierType.RELEASE_MASK). My engine only filtered release events through the shortcut path, but _handle_key still fed them to PinyinMode.feed_key, so release events were again treated as letters added to the buffer.

Fix commit 25b94ff: move release filtering to the very top of do_process_key_event, before any path.

Second Scream: Ctrl+Shift+M Does Nothing

I configured cycle_mode = "m", pressed it — the log said “pressed but no handler.” Pressed again — same log.

Two bugs stacked:

  • Shortcut parser parsing error: parse_shortcut("m") was mangling the modifier keys
  • The handler wasn’t registered for the parsed shortcut

The Timeline of Pitfalls

From aa4b094 to cddcb40, spanning about 2 weeks, I encountered 8 pitfalls, nearly every one of which caused ibus-daemon to kill itself.

Why ibus-daemon Always Kills Itself

Many of my bugs weren’t individually fatal — but any bug was fatal because of IBus’s process model:

  • ibus-daemon is a long-running process; if it dies, the entire desktop input method must restart.
  • Engine process abnormal exit → ibus-daemon kills itself by default (to avoid dirty state).
  • So any uncaught AttributeError, KeyError, IndexError in the engine silences the entire desktop.

The funniest one: I changed _PI_2 usage in tux_im/asr/overlay.py, and typing j (Pinyin j) killed the whole daemon — because the Wubi heuristic accessed the wrong attribute.

Last modified: 2026年6月25日

Author

Comments

Write a Reply or Comment

Your email address will not be published.