In our case, we use a world plugin which communicates with a docker-like tool for our drone firmwares. Whenever something bad happens with the firmwares, the plugin stops the world. We never restart the world after it has been stopped, we just quit gazebo, so I don't know if that works. Stopping the world ultimately destroys the world plugins so it won't work in our case, but it should work in a system plugin.
I added a system plugin example that you can try like so:
gzserver -s plugins/libStopWorldPlugin.so
Unfortunately, once the world is stopped, it can't be restarted from a plugin because we leave the while loop in Server::Run() and enter gazebo shutdown procedure. This pull request is still useful to stop the world gracefully from within a plugin.
Looking at the code I can not say if the changes in the destroy/disable/delete sequences are safe but playing with the simulator I was not able to make it to fail and all the shutdowns were fine for me even playing with gazebo_ros_pkgs on top of this PR. Let's wait for the results of the CI but I did not found big problems. Thanks Olivier!
I fixed the transport tests because Publisher, PublicationTransport and Publication must be shared objects (now that they inherit from enable_shared_from_this). There is still an issue with gz_TEST that I have not yet solved: Publisher is instantiated by gz model as a shared_ptr but its call to publication->Publish may result in an exception being thrown depending on when Publisher::OnPublishComplete is called: