Skip to content

Use QueuedConnection for signals in QCoroNetworkReply#245

Merged
danvratil merged 1 commit intomainfrom
231-crash-when-qnetworkreply-is-aborted-due-to-timeout
Sep 27, 2024
Merged

Use QueuedConnection for signals in QCoroNetworkReply#245
danvratil merged 1 commit intomainfrom
231-crash-when-qnetworkreply-is-aborted-due-to-timeout

Conversation

@danvratil
Copy link
Collaborator

The common pattern (even the one shown in our docs) of using QCoro with QNetworkReply is a local stack-allocated QNAM, making a request and then co_awaiting on the returned QNetworkReply. Once the coroutine is resumed, it likely returns, destroying the QNAM with it. The problem is, that after the coroutine returns, the execution returns back into the code inside QNetworkReply that emitted the signal, which then leads to invalid memory access, since the code has likely been already destroyed alongside the QNAM. Surprisingly, on Linux this does not crash and even ASAN does not detect it (would likely need to compile Qt with ASAN), but Valgrind was able to catch the invalid memory access inside Qt. On Windows this just crashes.

The solution is to use QueuedConnection between QNetworkReply and QCoro, so that we can be sure that by the time our code is called (leading to the destruction of QNAM), no code in the QNAM or its associated classes is being executed, so the destruction is clear.

I had to resort to some hackery to keep the QCoro struct binary compatible, so more cruft to be removed in 1.0.

Fixes #231

@danvratil danvratil force-pushed the 231-crash-when-qnetworkreply-is-aborted-due-to-timeout branch 4 times, most recently from 26f8d75 to ece2678 Compare September 27, 2024 12:51
The common pattern (even the one shown in our docs) of using QCoro with
QNetworkReply is a local stack-allocated QNAM, making a request and then
co_awaiting on the returned QNetworkReply. Once the coroutine is resumed,
it likely returns, destroying the QNAM with it. The problem is, that after
the coroutine returns, the execution returns back into the code inside
QNetworkReply that emitted the signal, which then leads to invalid memory
access, since the code has likely been already destroyed alongside the
QNAM. Surprisingly, on Linux this does not crash and even ASAN does not
detect it (would likely need to compile Qt with ASAN), but Valgrind was
able to catch the invalid memory access inside Qt. On Windows this just
crashes.

The solution is to use QueuedConnection between QNetworkReply and QCoro,
so that we can be sure that by the time our code is called (leading
to the destruction of QNAM), no code in the QNAM or its associated
classes is being executed, so the destruction is clear.

I had to resort to some hackery to keep the QCoro struct binary
compatible, so more cruft to be removed in 1.0.

Fixes #231
@danvratil danvratil force-pushed the 231-crash-when-qnetworkreply-is-aborted-due-to-timeout branch from ece2678 to 513723d Compare September 27, 2024 12:52
@danvratil danvratil merged commit 37994c0 into main Sep 27, 2024
@danvratil danvratil deleted the 231-crash-when-qnetworkreply-is-aborted-due-to-timeout branch September 27, 2024 13:25
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.

Crash when QNetworkReply is aborted due to timeout

1 participant