Bug 1777849 - Disable FEATURE_THREADSAFE_GL on libX11 < 1.7. r=gfx-reviewers,ahale

LibX11 versions prior to 1.7 have a race condition that made it unsafe to use
in multiple threads. Since Firefox 104, we created a CanvasRender thread that
is used to service WebGL commands off the Renderer thread so that WebGL does
not block WebRender. If WebGL uses GLX, this can lead us to using GLX on the
two different threads. In combination with an unsafe version of libX11, this
can lead to severe instability.

We already have a FEATURE_THREADSAFE_GL in place to denote this, which was
currently used mainly for Nouveau which is also unsafe to use on multiple
threads. If this feature fails, the CanvasRender thread is not used, and
all WebGL commands go back to being on the Renderer thread as normal, avoiding
the problem.

Thus, this detects the presence of libX11 version 1.7 or greater, and if not
found, we disable FEATURE_THREADSAFE_GL to disable the CanvasRender thread.

Differential Revision: https://phabricator.services.mozilla.com/D170992
This commit is contained in:
Lee Salzman 2023-02-25 07:27:31 +00:00
parent 17f87db988
commit 0621e7027b
2 changed files with 20 additions and 0 deletions

View file

@ -15,6 +15,7 @@
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <dlfcn.h>
#include "mozilla/gfx/Logging.h"
#include "mozilla/SSE.h"
@ -65,6 +66,7 @@ nsresult GfxInfo::Init() {
mHasMultipleGPUs = false;
mGlxTestError = false;
mIsVAAPISupported = false;
mIsX11ThreadSafe = false;
return GfxInfoBase::Init();
}
@ -524,6 +526,14 @@ void GfxInfo::GetData() {
mIsWayland = GdkIsWaylandDisplay();
mIsXWayland = IsXWaylandProtocol();
// Bug 1777849 - LibX11 versions prior to 1.7 have a race condition if it is
// used in more than one thread. The symbol "XSetIOErrorExitHandler" was added
// to the API in version 1.7, so we check for this symbol here to verify that
// libX11 is safe to use in multiple threads.
if (!mIsWayland) {
mIsX11ThreadSafe = dlsym(RTLD_DEFAULT, "XSetIOErrorExitHandler") != nullptr;
}
if (!ddxDriver.IsEmpty()) {
PRInt32 start = 0;
PRInt32 loc = ddxDriver.Find(";", start);
@ -958,6 +968,15 @@ nsresult GfxInfo::GetFeatureStatusImpl(
return NS_OK;
}
if (aFeature == nsIGfxInfo::FEATURE_THREADSAFE_GL && !mIsWayland &&
!mIsX11ThreadSafe) {
// Bug 1777849 - LibX11 versions before 1.7 are not thread-safe, so using
// GLX on multiple threads is not thread-safe either.
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION;
aFailureId = "FEATURE_FAILURE_THREADSAFE_GL";
return NS_OK;
}
return GfxInfoBase::GetFeatureStatusImpl(
aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os);
}

View file

@ -113,6 +113,7 @@ class GfxInfo final : public GfxInfoBase {
bool mHasMultipleGPUs;
bool mGlxTestError;
bool mIsVAAPISupported;
bool mIsX11ThreadSafe;
void AddCrashReportAnnotations();
};