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

Workaround for ogre crash on shutdown #1033

Merged
merged 15 commits into from
Aug 16, 2024
105 changes: 100 additions & 5 deletions ogre/src/OgreRenderEngine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ typedef khronos_intptr_t GLintptr;

# include <sstream>

#include <OgreDynLib.h>
#include <OgreDynLibManager.h>
#include <OgrePlugin.h>

#include <gz/plugin/Register.hh>

#include <gz/common/Console.hh>
Expand Down Expand Up @@ -66,6 +70,84 @@ class gz::rendering::OgreRenderEnginePrivate
using namespace gz;
using namespace rendering;

// Plugin loading and unloading code adapted from Ogre.
// Unloading the RenderSystem_GL plugin was found to cause a crash when the
// rendering thread exits. This only happens on Ubuntu 24.04 when running
// ogre using system debs, see
// https://github.com/gazebosim/gz-rendering/issues/1007
// To workaournd ths issue, we adapth the code for loadng and unloading
iche033 marked this conversation as resolved.
Show resolved Hide resolved
// ogre plugin here. We load the RenderSystem_GL library manually and store it
// in gz-rendering and on shutdown we stop the plugin and delete the lib without
// unloading it.
// \todo(iche033) Find a proper way to unload the library without causing a
// crash.
typedef void (*DLL_START_PLUGIN)(void);
scpeters marked this conversation as resolved.
Show resolved Hide resolved
typedef void (*DLL_STOP_PLUGIN)(void);
std::vector<Ogre::DynLib *> mPluginLibs;

void loadPlugin(const std::string &_pluginName)
{
// Load plugin library
Ogre::DynLib *lib = OGRE_NEW Ogre::DynLib(_pluginName);
lib->load();
if (std::find(mPluginLibs.begin(), mPluginLibs.end(), lib) ==
mPluginLibs.end())
{
mPluginLibs.push_back(lib);
// Call startup function
#ifdef __GNUC__
__extension__
#endif
DLL_START_PLUGIN pFunc = (DLL_START_PLUGIN)lib->getSymbol("dllStartPlugin");
if (!pFunc)
OGRE_EXCEPT(Ogre::Exception::ERR_ITEM_NOT_FOUND,
"Cannot find symbol dllStartPlugin in library " + _pluginName,
"Ogre::Root::loadPlugin");
pFunc();
}
}

void unloadPlugin(Ogre::DynLib *_pluginLib)
{
// Call plugin shutdown
#ifdef __GNUC__
__extension__
#endif
DLL_STOP_PLUGIN pFunc = reinterpret_cast<DLL_STOP_PLUGIN>(
_pluginLib->getSymbol("dllStopPlugin"));
pFunc();

// Unload library & destroy
// \todo(iche033) Unloading the RenderSystem_GL system causes a crash
// on thread exit so commented out for now.
// _pluginLib->unload();
delete _pluginLib;
}

/// A dummy plugin class that is installed to the ogre root before shutdown.
/// We use this as a hook to get a callback from ogre root when all plugins
/// are being unloaded. This is so that we can unload the RenderSystem_GL
/// at the right time.
class DummyPlugin : public Ogre::Plugin
iche033 marked this conversation as resolved.
Show resolved Hide resolved
{
public: DummyPlugin() {}
public: const Ogre::String& getName() const
{
return pluginName;
}
public: void install() {}
public: void initialise() {}
public: void shutdown() {}
public: void uninstall()
{
for (auto &lib : mPluginLibs)
unloadPlugin(lib);
mPluginLibs.clear();
}
const Ogre::String pluginName = "dummy";
};
DummyPlugin gDummyPlugin;

//////////////////////////////////////////////////
OgreRenderEnginePlugin::OgreRenderEnginePlugin()
{
Expand Down Expand Up @@ -118,9 +200,13 @@ void OgreRenderEngine::Destroy()

if (ogreRoot)
{
// TODO(anyone): do we need to catch segfault on delete?
try
{
// TODO(anyone): do we need to catch segfault on delete?
// Install a dummy plugin that allows use to manually shutdown ogre
iche033 marked this conversation as resolved.
Show resolved Hide resolved
// and stop the RenderSystem_GL library.
this->ogreRoot->installPlugin(&gDummyPlugin);

delete this->ogreRoot;
}
catch (...)
Expand Down Expand Up @@ -458,17 +544,26 @@ void OgreRenderEngine::LoadPlugins()

for (piter = plugins.begin(); piter != plugins.end(); ++piter)
{

bool isGLPlugin = std::string(*piter).find("RenderSystem_GL")
!= std::string::npos;
try
{
// Load the plugin into OGRE
this->ogreRoot->loadPlugin(*piter+extension);
// Load the plugin
if (isGLPlugin)
loadPlugin(*piter+extension);
else
this->ogreRoot->loadPlugin(*piter+extension);
}
catch(Ogre::Exception &e)
{
try
{
// Load the debug plugin into OGRE
this->ogreRoot->loadPlugin(*piter+"_d"+extension);
// Load the debug plugin
if (isGLPlugin)
loadPlugin(*piter+"_d"+extension);
else
this->ogreRoot->loadPlugin(*piter+"_d"+extension);
}
catch(Ogre::Exception &ed)
{
Expand Down