Skip to content

Always invoke binary reply callback when message handler throws#20

Merged
lhoward merged 1 commit into
mainfrom
fix/always-call-binary-reply-on-handler-error
Apr 14, 2026
Merged

Always invoke binary reply callback when message handler throws#20
lhoward merged 1 commit into
mainfrom
fix/always-call-binary-reply-on-handler-error

Conversation

@lhoward

@lhoward lhoward commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • FlutterPlatformMessenger.setMessageHandler (Darwin/iOS/Android) and FlutterDesktopMessenger.setMessageHandler (Linux/eLinux) both spawn a Task to call the user-supplied FlutterBinaryMessageHandler. If that handler throws, the task exits without ever calling the reply callback (FlutterBinaryReply / sendResponse).
  • The Flutter engine retains the MallocMapping-owned message buffer until the reply callback is invoked. When it is never called, the buffer leaks permanently — one per unacknowledged message.
  • This matches the pattern described in Platform channel memory leak on macOS embedder flutter/flutter#159363. Observed in practice as unbounded growth on oca/property_event and oca/set_property platform channels in InfernoUI (PADL/inferno_ui#52): 90 leaks (~3.7 KB) after 22 seconds of normal operation, growing without bound.

Fix

Wrap the try await handler(message) call in a do/catch in both messenger implementations and call callback(nil) / sendResponse(..., response: nil) in the catch block, ensuring the reply is always delivered regardless of handler outcome.

Test plan

  • Build and run InfernoUI on macOS with an active OCA device
  • Run leaks <pid> after 2+ hours of operation; confirm zero leaks attributed to oca/property_event or oca/set_property
  • Confirm existing unit tests pass

🤖 Generated with Claude Code

If the FlutterBinaryMessageHandler throws, the reply callback was never
called, leaving the Flutter engine's MallocMapping-owned message buffer
permanently retained. This matches the pattern described in
flutter/flutter#159363 where every unacknowledged platform message leaks
~96–192 bytes.

Fix both FlutterPlatformMessenger (Darwin/iOS/Android) and
FlutterDesktopMessenger (Linux/eLinux) to always call the reply with nil
on error, so the engine can release the allocation regardless of handler
outcome.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lhoward lhoward merged commit 34e9a38 into main Apr 14, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant