applib/touch_service: don't re-init the event node on re-subscribe#1784
Open
tsutomu1984-hub wants to merge 1 commit into
Open
applib/touch_service: don't re-init the event node on re-subscribe#1784tsutomu1984-hub wants to merge 1 commit into
tsutomu1984-hub wants to merge 1 commit into
Conversation
touch_service_subscribe re-initialized state->raw_event_info on every call, zeroing its embedded list_node. Because a click_config_provider re-runs on each window appear (ScrollLayer/MenuLayer/swap_layer all subscribe from there), the node's linkage was zeroed while it was still linked in the per-task event subscriber list. A later unsubscribe then found the stale node via list_find and skipped the kernel-side unsubscribe, leaking the touch subscriber count. On KernelMain (which is never torn down like an app) the leak is permanent, so touch_has_app_subscribers() stayed true and suppressed the touch-to-click synthesis bridge everywhere (e.g. the Music app) after visiting any touch-subscribing screen. Only initialize the node on the first subscribe; later calls just refresh the handler/context. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: tsutomu sasaki <tsutomu1984@gmail.com>
This was referenced Jul 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
touch_service_subscribe()re-initializedstate->raw_event_info(the per-taskEventServiceInfo) on every call, zeroing its embeddedlist_node. When a subscriber re-subscribes while already subscribed, this corrupts the per-task event-service subscriber list and leaks the kernel-side touch subscriber count. This moves the initialization inside the "first subscribe" guard.Why it happens
The touch service keeps a single per-task subscription, guarded by
state->raw_subscribedso it registers only once. But theraw_event_infoassignment sat before that guard, so it ran on every call:A
ClickConfigProviderre-runs on every window appear (window_set_on_screen→prv_call_click_provider, and the modal manager re-running it on focus). Widgets that subscribe to touch from their click config provider therefore calltouch_service_subscribe()again on each appear. On the 2nd+ call:raw_event_infois re-initialized → its embeddedlist_node.next/prevare zeroed while the node is still linked in the task'sevent_service_clientsubscriber list.raw_subscribedguard skips the real (re-)subscribe, so the corruption is silent.Later, on unsubscribe:
event_service_client_unsubscribe()→sys_event_service_client_unsubscribe()callslist_remove(), but with zeroednext/prevthe node isn't properly unlinked (a prior node still points to it).list_find(..., handler->type)then finds the stale, still-linked node (its.typewas re-set toPEBBLE_TOUCH_EVENT), concludes "another handler for this type still exists", and skips the kernel-side unsubscribe.remove_subscriber_callbacknever fires → the touch subscriber count (services/touch/touch.c) leaks.On KernelMain the leak is permanent (KernelMain is never torn down like an app, so
event_service_clear_process_subscriptionsnever cleans it up). A leaked count keepstouch_has_app_subscribers()permanently true.The fix
Initialize
raw_event_infoonly on the first subscribe (inside the!raw_subscribedguard); later calls just refreshraw_handler/raw_context. Thelist_nodestays intact while linked, so unsubscribe reaches the kernel and the count balances.Relationship to #1773
touch_servicecurrently has no widget-level callers onmain(only the manufacturing touch test, which subscribes once), so this bug is latent onmaintoday. It becomes reachable for any widget that subscribes from its click config provider — i.e. the ScrollLayer/MenuLayer touch support in #1773 and other in-flight touch work. Landing this fix first lets those PRs build on a correcttouch_service.Testing
Compiles into the obelix (Pebble Time 2) firmware. Verified on-device with a build combining this fix with ScrollLayer/MenuLayer touch, swap_layer touch, and a click-synthesis bridge: before the fix, visiting a touch-subscribing screen then a non-subscribing one left the count leaked (touch suppressed downstream); after, the count returns to baseline and behavior is correct.
🤖 Generated with Claude Code