Stop the JSON API before plugins delete their resource providers - #6
Merged
defnax merged 1 commit intoAug 14, 2026
Conversation
rsGlobalShutDown() stopped the JSON API almost last, after stopPlugins(). A plugin that registered a JsonApiResourceProvider deletes it in its stop(), but the running restbed service still holds the restbed::Resource objects that provider returned, and their handlers capture it. Any request served between stopPlugins() and the fullstop at the end of the function therefore dereferences freed memory. The window is not theoretical: everything in between -- UPnP teardown, the auto-proxy shutdown, all registered service threads, the RsServer tick thread and the per-peer streamers -- can take tens of seconds, and a web interface polls throughout. Move the fullstop to the top of the function. It also keeps an API client from touching the configuration after ConfigFinalSave(), and it must stay outside the wasReady branch: retroshare-service and Android start the JSON API before login, so a shutdown from that state has to stop it too. Without this, a plugin has to restart the whole JSON API from its stop() to make deleting its own provider safe, which costs a burst-protection wait and brings the server back up in the middle of teardown.
Owner
|
this not mergeable i saw it today |
Author
|
#6 merges cleanly — it is a fast-forward on top of api-for-plugins, one commit, no conflict. I verified it locally with git merge-tree as well as on GitHub, which reports MERGEABLE. |
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.
One commit, already open standalone as RetroShare#366. Proposing it here as well on purpose — see the last section for why the duplication is deliberate.
The defect
RsServer::rsGlobalShutDown()stops the JSON API almost last, afterstopPlugins().A plugin that registered a
JsonApiResourceProviderdeletes it in itsstop(), but the running restbed service still holds therestbed::Resourceobjects that provider returned, and their handlers capture it —JsonApiServer::run()publishes them once at thread start and the service keeps them for its whole lifetime. Any request served betweenstopPlugins()and thefullstop()at the end of the function therefore dereferences freed memory.The window is not theoretical: everything in between — UPnP teardown, the auto-proxy shutdown, all registered service threads, the
RsServertick thread and the per-peer streamers — can take tens of seconds, and a web interface polls throughout.This moves the
fullstop()to the top of the function. Two details worth noting:ConfigFinalSave(), which runs a couple of lines below;wasReadybranch, because retroshare-service and Android start the JSON API before login, so a shutdown from that state has to stop it too. That is why the call cannot simply be hoisted into the existing block.Why it belongs in this PR
The defect is only reachable once a plugin can register a resource provider — which is exactly what this PR enables. Before it, no plugin in the tree has access to
RsJsonApi, so the code path does not exist.It also closes a merge-order trap. RetroShare/RetroShare#3289 no longer restarts the JSON API from
FeedReaderPlugin::stop(); that restart used to be what made deleting the provider safe, and this change is what replaces it. #3289 already declares a hard dependency on this PR — without it the plugin does not even compile, sinceRsPlugInInterfaces::mJsonApiwould not exist. Carrying the shutdown fix here therefore makes it impossible to merge #3289 without the protection, instead of relying on someone reading a note about merge order.On the duplication with RetroShare#366
RetroShare#366 stays open as a fallback: if this PR is delayed or dropped, the fix should still reach master on its own. Whichever lands first, the other becomes a no-op — the patch is identical, so git merges it without conflict — and I will close RetroShare#366 once this one is in.
Not build-tested. The MINGW64 workflow in this repo fails at "Checkout submodules" on every branch including master (it lists the super-project's submodules, which do not exist here), so its red mark is unrelated.