AtomTools: fix multiple material editor processes launching
Atom tools launch or check for the existence of a local server in order to prevent multiple application processes from running. These checks were being done far too late, after initialization and asset processing, leaving time for multiple processes to start before the server or checks. Zombie processes could start and run indefinitely without user interaction because the event loop was being entered despite the request to exit the application early. These changes launch the server and checks immediately after the application object is constructed and exit before any other work is done if the application will not be run. Signed-off-by: Guthrie Adams <guthadam@amazon.com>
This commit is contained in:
+2
-2
@@ -46,6 +46,8 @@ namespace AtomToolsFramework
|
||||
AtomToolsApplication(int* argc, char*** argv);
|
||||
~AtomToolsApplication();
|
||||
|
||||
virtual bool LaunchLocalServer();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AzFramework::Application
|
||||
void CreateReflectionManager() override;
|
||||
@@ -106,8 +108,6 @@ namespace AtomToolsFramework
|
||||
virtual void UnloadSettings();
|
||||
virtual void CompileCriticalAssets();
|
||||
virtual void ProcessCommandLine(const AZ::CommandLine& commandLine);
|
||||
virtual bool LaunchDiscoveryService();
|
||||
virtual void StartInternal();
|
||||
|
||||
static void PyIdleWaitFrames(uint32_t frames);
|
||||
|
||||
|
||||
+29
-52
@@ -152,7 +152,33 @@ namespace AtomToolsFramework
|
||||
|
||||
Base::StartCommon(systemEntity);
|
||||
|
||||
StartInternal();
|
||||
m_traceLogger.PrepareLogFile(GetBuildTargetName() + ".log");
|
||||
|
||||
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect();
|
||||
AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(
|
||||
&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized);
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml");
|
||||
|
||||
AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets();
|
||||
|
||||
LoadSettings();
|
||||
|
||||
AtomToolsMainWindowNotificationBus::Handler::BusConnect();
|
||||
|
||||
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow);
|
||||
|
||||
auto editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
|
||||
if (editorPythonEventsInterface)
|
||||
{
|
||||
// The PythonSystemComponent does not call StartPython to allow for lazy python initialization, so start it here
|
||||
// The PythonSystemComponent will call StopPython when it deactivates, so we do not need our own corresponding call to
|
||||
// StopPython
|
||||
editorPythonEventsInterface->StartPython();
|
||||
}
|
||||
|
||||
// Delay execution of commands and scripts post initialization
|
||||
QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); });
|
||||
|
||||
m_timer.start();
|
||||
}
|
||||
@@ -334,7 +360,7 @@ namespace AtomToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
bool AtomToolsApplication::LaunchDiscoveryService()
|
||||
bool AtomToolsApplication::LaunchLocalServer()
|
||||
{
|
||||
// Determine if this is the first launch of the tool by attempting to connect to a running server
|
||||
if (m_socket.Connect(QApplication::applicationName()))
|
||||
@@ -376,7 +402,7 @@ namespace AtomToolsFramework
|
||||
{
|
||||
AZ::CommandLine commandLine;
|
||||
commandLine.Parse(tokens);
|
||||
ProcessCommandLine(commandLine);
|
||||
QTimer::singleShot(0, [this, commandLine]() { ProcessCommandLine(commandLine); });
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -390,55 +416,6 @@ namespace AtomToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
void AtomToolsApplication::StartInternal()
|
||||
{
|
||||
if (WasExitMainLoopRequested())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::string fileName = GetBuildTargetName() + ".log";
|
||||
|
||||
m_traceLogger.PrepareLogFile(fileName.c_str());
|
||||
|
||||
if (!LaunchDiscoveryService())
|
||||
{
|
||||
ExitMainLoop();
|
||||
return;
|
||||
}
|
||||
|
||||
AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusConnect();
|
||||
AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast(
|
||||
&AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized);
|
||||
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml");
|
||||
|
||||
AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets();
|
||||
|
||||
LoadSettings();
|
||||
|
||||
AtomToolsMainWindowNotificationBus::Handler::BusConnect();
|
||||
|
||||
AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow);
|
||||
|
||||
auto editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
|
||||
if (editorPythonEventsInterface)
|
||||
{
|
||||
// The PythonSystemComponent does not call StartPython to allow for lazy python initialization, so start it here
|
||||
// The PythonSystemComponent will call StopPython when it deactivates, so we do not need our own corresponding call to
|
||||
// StopPython
|
||||
editorPythonEventsInterface->StartPython();
|
||||
}
|
||||
|
||||
// Delay execution of commands and scripts post initialization
|
||||
QTimer::singleShot(
|
||||
0,
|
||||
[this]()
|
||||
{
|
||||
ProcessCommandLine(m_commandLine);
|
||||
});
|
||||
}
|
||||
|
||||
bool AtomToolsApplication::GetAssetDatabaseLocation(AZStd::string& result)
|
||||
{
|
||||
AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
|
||||
@@ -28,9 +28,12 @@ int main(int argc, char** argv)
|
||||
AzQtComponents::AzQtApplication::InitializeDpiScaling();
|
||||
|
||||
MaterialEditor::MaterialEditorApplication app(&argc, &argv);
|
||||
if (!app.LaunchLocalServer())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app);
|
||||
app.installEventFilter(globalEventFilter);
|
||||
app.installEventFilter(new AzQtComponents::GlobalEventFilter(&app));
|
||||
|
||||
AZ::IO::FixedMaxPath engineRootPath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
|
||||
@@ -28,6 +28,12 @@ int main(int argc, char** argv)
|
||||
AzQtComponents::AzQtApplication::InitializeDpiScaling();
|
||||
|
||||
ShaderManagementConsole::ShaderManagementConsoleApplication app(&argc, &argv);
|
||||
if (!app.LaunchLocalServer())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
app.installEventFilter(new AzQtComponents::GlobalEventFilter(&app));
|
||||
|
||||
AZ::IO::FixedMaxPath engineRootPath;
|
||||
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
|
||||
@@ -35,13 +41,10 @@ int main(int argc, char** argv)
|
||||
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
}
|
||||
|
||||
auto globalEventFilter = new AzQtComponents::GlobalEventFilter(&app);
|
||||
app.installEventFilter(globalEventFilter);
|
||||
|
||||
AzQtComponents::StyleManager styleManager(&app);
|
||||
styleManager.initialize(&app, engineRootPath);
|
||||
|
||||
app.Start({});
|
||||
app.Start(AZ::ComponentApplication::Descriptor{});
|
||||
app.exec();
|
||||
app.Stop();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user