a3934cde9a
Three correctness gaps found in code review of the private-loop rewrite, all in how chansrv's thread and the IBus thread interact around `bus`: - xrdp_input_enable() read the shared `bus` pointer with no synchronization at all, despite the IBus thread being free to null it out (disconnect, teardown) at any time - a real use-after-free risk, not just a formality, since this function actively calls methods on it rather than just checking it's non-NULL. Fixed by taking a ref under state_mutex before touching it, and using that local reference for the rest of the call; bus's creation and teardown in xrdp_input_main_loop() now publish/clear the shared pointer under the same lock so the ref-under-lock pattern actually synchronizes against something. - xrdp_input_unicode_init()'s fast path trusted ibus_ready without re-checking the connection. ibus_ready and connection liveness normally change together, but there's a window between the underlying socket actually dying and the "disconnected" signal being dispatched on the IBus thread. A client that reconnects into that window would get a false "unicode input is supported" advertisement it could never actually use. Now double-checks ibus_bus_is_connected() before taking the fast path. - That staleness check can't just flip ibus_ready and fall through to spawning a new thread - the old one may still be alive and about to touch bus/g_engine itself, racing the new thread's own setup. Now asks the stale thread to shut down (g_main_loop_quit, safe to call cross-thread) and waits on the exit condvar before proceeding, so there's never more than one IBus thread alive at a time. Verified: 20 back-to-back xrdp_input_unicode_init() calls on a healthy connection all take the fast path correctly (no spurious thread restarts); 5 kill/restart cycles still show no thread leak; an 18-char rapid-fire send against a real focused GTK entry still lands every character in order with zero drops after these changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>