Fix safety issues with AsyncClient destruction in user callbacks - #123
willmmiles wants to merge 5 commits into
Conversation
Ensure that it is safe to destruct an AsyncClient from any user callback. Fixes a guaranteed use-after-free if `close()` was called inside `onData()`.
There was a problem hiding this comment.
Pull request overview
Adds callback-lifetime tracking to prevent AsyncClient use-after-free during user callbacks.
Changes:
- Tracks client validity across nested callbacks.
- Safely stops receive processing after closure/destruction.
- Initializes
_rx_ack_lenand removes a duplicate include.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/AsyncTCP.h |
Adds callback context state and moves ackLater() implementation. |
src/AsyncTCP.cpp |
Implements callback safety, receive cleanup, and initialization fixes. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Arg. Upon re-re-review, I think there might still be something off with the |
The old _lwip_fin function was entirely unreferenced.
Per @Copilot, it's only available in newer GCCs.
If we're closing as a response to some message from the remote end, acknowledge the last processed pbuf first. This ensures that we'll send FINs instead of RSTs on correctly processed messages.
Updated with a fix for this. To be clear, the issue of incorrectly sending RSTs if we |
|
Hold off on this one for now. I'm working on a better way using |
Ensure no use-after-frees occur if the
AsyncClientobject is destroyed while in a user callback. This guarantees correct behavior if user code callsclose()in an event callback (such asonData,onPacket,onTimeout, etc.) and frees theAsyncClientin theonDisconnect()callback.Note that this does not insulate the user callback code itself against internal use-after-free events, such as using a captured lambda value after destroying the
AsyncClientand thus thestd::functionstoring the capture. Any user code that could destruct its ownAsyncClientmust be cognizant of the risks. We may want to consider an explicit "deferred close" API to make it easier for clients to reason about their own code.Includes a couple of other little tweaks:
_rx_ack_lenis initialized