Repository navigation
ClientSocket_Qt: give signal completions shared ownership - #1822
Merged
Merged
Conversation
The 5 s completion wait in send() was only safe while the queued call ran within the window: the completion object was stack-local, so if the wait expired and the event thread delivered the queued internal_send() later, the slot wrote through a dead stack pointer (stack-use-after-return) - the same issue ServerSocket_Qt had, fixed the same way in the ServerSocket_Qt work. The signal now passes QSharedPointer<SendData> by value: the queued call's own copy keeps the payload alive until it runs (or is discarded with the socket), so the wait's expiry is safe.
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.
Follow-up to the Mac Intel CI crash investigation (#1811, #1812, #1817, #1819).
The issue.
ClientSocket_Qt::send()kept the completion object stack-local and passed a raw pointer through a queued Qt signal:If the event thread delivers the queued call after the 5 s wait expires, the slot runs
sock->write(...), then lockssend_data->lock, writessend_data->bytes_sent/send_data->done, and callssend_data->cv.notify_all()— all through a dead stack pointer on the calling thread's stack (stack-use-after-return). The corrupted bytes then explode later where that stack region is reused.This is the same issue that
ServerSocket_Qthad and already fixed (shared-ownership completions, see theQSharedPointer<SendData>/QSharedPointer<CloseCompletion>inServerSocket_Qt.cppand its commit history): the server'ssend()/close_connection()wait on the same 5 s pattern, but their payloads are heap-owned.ClientSocket_Qt::send()was the one remaining raw-pointer crossing in the Qt socket backends.The fix. The signal now passes
QSharedPointer<SendData>by value; the queued call's own copy keeps the payload alive until it runs (or is discarded with the socket). The 5 s wait stays — it still bounds the call whenclose()destroys the socket before the queued event runs, and with shared ownership the expiry is now safe.Context. The Mac Intel runner has been crashing intermittently in
Test_Sockets_RapidReconnect<ClientSocket_Qt, ServerSocket_Qt>(backtraces on #1812/#1819 show the fault in aWaiter::wait_forstack frame in that test). This closes the one known way for the test's socket plumbing to corrupt a pool thread's stack. Whether it accounts for every crash will show in CI: this test hammerssend()50× per run, and the crash has been hitting it most reliably.