Skip to content
This repository was archived by the owner on Feb 15, 2023. It is now read-only.

Fixed socket deletion error#59

Merged
nikhilm merged 2 commits intonikhilm:masterfrom
Skycoder42:master
Dec 29, 2020
Merged

Fixed socket deletion error#59
nikhilm merged 2 commits intonikhilm:masterfrom
Skycoder42:master

Conversation

@Skycoder42
Copy link
Copy Markdown
Contributor

Deleting the socket in the destructor can cause a crash when shutting down the app. By moving it to the socketDisconnectedand deleting it with deleteLater fixed the issue.

deleting the socket in the destructor can cause a crash when shutting down the app. By moving it to the socketDisconnected and deleting it with "deleteLater" fixed the issue
{
deleteLater();
invalidateRequest();
m_socket->deleteLater();
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the patch. Please fix the indentation here.

Also, I do not understand why this segfaults in the dtor? Is it because m_socket is already being freed somewhere else?

@Skycoder42
Copy link
Copy Markdown
Contributor Author

I'm not completly shure where the crash comes from, but I do know the circumstances:

If there is an open connection when the app quits, the original line delete m_socket; will assert with a segfault. Moving the deletion helped. It doesn't make much sense, because if it was deleted multiple times, this schould not change anything, or only using deleteLater should be enough.

The fact that it only happens while quitting lets me assume the "something" happens between the socketDisconnected and the destructor, and this something is responsible for the crash. (it could be inside the sockets destructor itself).

@gunoodaddy
Copy link
Copy Markdown

I think this crash must be solved too. I have a little bit of different solution below.
in QHttpConnection's construct, just change the socket variable's parent to QHttpConnection. it means that the ownership of socket move to QHttpConnection from QTcpServer.
like this : socket->setParent( this ).
It's more simpler..

@suy
Copy link
Copy Markdown

suy commented Dec 20, 2020

The socket is deleted by the parent. The library is double deleting the object. It's explained in the documentation of QTcpServer::nextPendingConnection.

@nikhilm
Copy link
Copy Markdown
Owner

nikhilm commented Dec 24, 2020

https://stackoverflow.com/questions/28820450/how-to-safely-delete-a-qtqtcpsocket

Deleting a socket obtained from QTcpServer seems to be correctly handled.

@suy
Copy link
Copy Markdown

suy commented Dec 24, 2020

Not if the parent QTcpServer is deleted first, then deletes its children, then the socket gets double deleted by the library. The problem is not QTcpServer doing double deletion (once deleted, the parent gets notified and removes it from its children list automatically), is QHttpServer doing it.

I can't tell with 100% certainty that QHttpServer is being used right, but I think it is. I was working in our project, used Valgrind to check for possible leaks in one part of the code, then it reported a leak in our class, which uses QSimpleRestServer, which in turn uses QHttpServer. Then I ended up fixing the leak in the other pull request and the double deletion detected here.

Adding some logging I get this (the connection is established, then the application is closed while it's on):

    49.275 QHttpServer destroyed
    49.275 QTcpServer destroyed
    49.275 QTcpSocket destroyed
    49.275 QHttpConnection destroyed

In another case (the connection times out, and after a while I close the application) I have this instead:

   136.193 QHttpConnection destroyed
   136.194 QTcpSocket destroyed
   806.278 QHttpServer destroyed
   806.278 QTcpServer destroyed

@nikhilm
Copy link
Copy Markdown
Owner

nikhilm commented Dec 29, 2020

Thank you everybody for the input, and @suy for the clear explanation! I'll merge this. Again, I haven't done Qt development in 6-7 years, so I'm not sure how this specific change fixes the problem @suy outlined, because isn't there now a double-free happening in socketDisconnected? Or is it guaranteed that that will be signaled prior to QTcpServer deletion? Or is this something to do with calling deleteLater() being safe on an already deleted object?

@nikhilm nikhilm merged commit 30ac571 into nikhilm:master Dec 29, 2020
@suy
Copy link
Copy Markdown

suy commented Dec 29, 2020

Just to clarify: I did not apply this patch verbatim to our copy in our codebase, because I found this PR later. I wrapped the socket in a QPointer, because it automatically becomes null when the socket would be destroyed (and deleting nullptr is safe; or alternatively, check for null before deletion if that suits your style better). I did not write that network code, so I don't know what it's supposed to do, and I'm not able to test it "for real". Hence, the more conservative approach.

FYI, deleteLater is not supposed to fix a double deletion per se. However, if you call it twice the delete events will be queued, but only the first one will actually delete the object, if still alive because the parent has not done it itself. I don't know the intention of the patch as I've just skimmed at how the class works.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants