macOS OpenGL initialization / security entitlements
See original GitHub issueWhen building a standalone binary of the CQ-Editor for macOS, the app may or may not crash depending on its launch context. That is:
- direct from terminal
- inside
lldb
- macOS
launchd
when double-clicked in the Finder - also macOS
launchd
when launched from the terminal with theopen
command
Each mechanism may or may not trigger macOS gatekeeper security and execute the app inside a “sandbox” with path randomization. This path randomization is usually transparent from the point of view of the python introspection, but at a lower level, the oce
core accesses the file system to initialize the OpenGL driver as follows:
- In
OCC/Core/Graphic3d.py
,ShadersFolder()
is called which in turn calls the binary object function_Graphic3d.Graphic3d_ShaderProgram_ShadersFolder(*args)
- This function is in
oce/Graphic3d_ShaderProgram.cxx
and it is as follows:
// =======================================================================
// function : ShadersFolder
// purpose :
// =======================================================================
const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder()
{
static Standard_Boolean THE_IS_DEFINED = Standard_False;
static TCollection_AsciiString THE_SHADERS_FOLDER;
if (!THE_IS_DEFINED)
{
THE_IS_DEFINED = Standard_True;
OSD_Environment aDirEnv ("CSF_ShadersDirectory");
THE_SHADERS_FOLDER = aDirEnv.Value();
if (THE_SHADERS_FOLDER.IsEmpty())
{
OSD_Environment aCasRootEnv ("CASROOT");
THE_SHADERS_FOLDER = aCasRootEnv.Value();
#ifdef OCE_INSTALL_DATA_DIR
if (THE_SHADERS_FOLDER.IsEmpty()) {
THE_SHADERS_FOLDER = OCE_INSTALL_DATA_DIR;
}
#endif
if (!THE_SHADERS_FOLDER.IsEmpty())
{
THE_SHADERS_FOLDER += "/src/Shaders";
}
}
if (THE_SHADERS_FOLDER.IsEmpty())
{
std::cerr << "Both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n"
<< "At least one should be defined to use standard GLSL programs.\n";
Standard_Failure::Raise ("CSF_ShadersDirectory and CASROOT are undefined");
return THE_SHADERS_FOLDER;
}
const OSD_Path aDirPath (THE_SHADERS_FOLDER);
OSD_Directory aDir (aDirPath);
const TCollection_AsciiString aProgram = THE_SHADERS_FOLDER + "/Declarations.glsl";
OSD_File aProgramFile (aProgram);
if (!aDir.Exists()
|| !aProgramFile.Exists())
{
std::cerr << "Standard GLSL programs are not found in: " << THE_SHADERS_FOLDER.ToCString() << std::endl;
Standard_Failure::Raise ("CSF_ShadersDirectory or CASROOT is set incorrectly");
return THE_SHADERS_FOLDER;
}
}
return THE_SHADERS_FOLDER;
}
Depending on runtime sandboxing, the path that this function infers may turn out to be incorrect or obscured. Therefore, when it tests Exists()
at the end of the function it raises the error. It is difficult to tell if this function falls back on the hardcoded OCE_INSTALL_DATA_DIR
since that will defined when oce is built. If it is, then it is yet another mechanism to not find the Shaders folder.
At the end of the day, the program crashes because OpenGL does not get initialized since it cannot find its Shaders/etc. resources in oce/src
.
The secondary mechanism of failure related to #108 is that the evaluation of security entitlements delays OpenGL driver initialization and creates a fatal race condition during app initialization due to early requests to draw axis lines in the 3D viewer.
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (3 by maintainers)
@jmwright @adam-urbanczyk Good news! All fixed!
I added some logic to
run.py
to introspect the full absolute path of the application, lookup theCSF_ShadersDirectory
env variable, and perform a runtime substitution of the env variable with the full path. It only does this if it detects the sys.platform == “darwin”. I also added some platform specific logic to initialize QApplication–this silences nuisance warnings about initializing pyqtgraph after QApplication. The application bundle launches in all contexts and includes pretty dock icons for macOS. Next, I’ll make a DMG builder script with signing and pretty icons so that macOS users should hopefully be able to download and install in one turnkey step just like any other macOS app.This issue can be closed since the PR #111 addresses this problem with run time substitution of the environment variable for CSF Shaders. Platform specific guards ensure that this occurs only for macOS targets.