Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big memory leak, on client disconnect, in server that is started with the runInBackground argument set to TRUE #570

Open
JorisHansMeijer opened this issue Apr 14, 2023 · 9 comments
Assignees
Labels

Comments

@JorisHansMeijer
Copy link
Contributor

When starting the server with the runInBackground argument set to TRUE a big memory leak happens each time a client disconnects. This is because the client_thread is not joined after detach. I fixed this by adding pthread_detach(cl->client_thread); at the end of the clientInput function in main.c (just before the return).

Because no the thread doesn't need to be joined I have also removed the join that was there in rfbShutdownServer. This join will only join the clients that are active at the time of stopping the server (not the clients that have disconnected before rfbShutdownServer was called).

@bk138
Copy link
Member

bk138 commented Apr 14, 2023

Thanks for finding out! Could you be so kind and file a pull request? This way, we can also have proper author credits :-)

@JorisHansMeijer
Copy link
Contributor Author

Done

@bk138 bk138 reopened this Apr 16, 2023
@bk138 bk138 linked a pull request Apr 16, 2023 that will close this issue
@bk138 bk138 self-assigned this Jun 21, 2023
@bk138
Copy link
Member

bk138 commented Aug 5, 2023

list of things to check for @bk138

  • win32 threads detach, how would it work
  • test detach case for "client disconnects"
  • test detach case for "server shuts down with active clients"
  • think about pipe-notify machinery -> is for breaking the select() wait in client thread in close event

@bk138 bk138 closed this as completed in 8560a5a Aug 5, 2023
@bk138 bk138 added this to the Release 0.9.15 milestone Aug 5, 2023
bk138 added a commit that referenced this issue Aug 30, 2023
This reverts commit 8560a5a.

It caused several crashes when ending a server: client threads would
sometimes linger around until after the server was stopped and its
rfbScreen internals free()ed, with these client threads trying to access
rfbScreen and friends: 💣.

Reopens #570
@bk138 bk138 reopened this Aug 30, 2023
@bk138
Copy link
Member

bk138 commented Aug 30, 2023

This needs some more love as 8560a5a alone caused bk138/droidVNC-NG#163

  • re-apply 8560a5a ?
  • rework rfbShutdownServer
  • rework rfbCleanupServer
  • test test test (with additional delays injected)

@JorisHansMeijer
Copy link
Contributor Author

JorisHansMeijer commented Sep 1, 2023

Is it correct that the problem happens a shutting down the server? Looking at the code again I can see that pthread_join would wait for the client thread to finish execution. Removing pthread join (as detached trhead's can't be joined) would also remove the waiting for the client to finish code. So the solution seems to be to just wait for the client to finish instead of the previous pthread_join call.

@bk138
Copy link
Member

bk138 commented Sep 1, 2023

Exactly. How would we best wait for a detached thread to finish?

@JorisHansMeijer
Copy link
Contributor Author

Maybe the best way would be using pthread_kill, it can be used in a simulation mode were it just test if the signal could be send. In this way it is possible to know if a thread is still running. Example (untested):
while(pthread_kill(currentCl->client_thread, 0) != ESRCH){
sleep some ms..
}

@bk138
Copy link
Member

bk138 commented Sep 1, 2023

Hmm, busy sleep sounds like we can do better? Maybe a condition variable or the like? (disclaimer: I'm not soo familiar with pthreads...)

@JorisHansMeijer
Copy link
Contributor Author

JorisHansMeijer commented Sep 1, 2023

Some more digging reveals that using pthread_kill on a canceled thread is not a good way to go (in linux I believe it is fine, but not for all pthread implementations out there). Maybe a better way to go is keep track of the thread termination in the client object (add running variable, set it at thread start, clear it at thread detach) and wait for that to clear in the termination function.

The time between stopping the server and waiting for the threads to finish should not be long so a loop with a short sleep would not be that much of a issue I think (just a couple of ms using nanosleep on linux and something similar on windows).

As a alternative it is possible to NOT detach the threads that are still running at server termination (conditional detach). Than the original join can be put back. However this might cause problems with clients that are just in the process of detaching when the server is stopped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants