Fix EGL crash for KDE/Plasma (rfbz#4303)
This commit is contained in:
parent
2e09c839ae
commit
280f7a2910
203
egl_crash.patch
203
egl_crash.patch
@ -1,153 +1,80 @@
|
||||
From 61bd107cc64f158d7a3e40877c47aa565651487a Mon Sep 17 00:00:00 2001
|
||||
From 758b525463cd00478bf071d477ab58c92414b852 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Brenneman <kbrenneman@nvidia.com>
|
||||
Date: Mon, 24 Oct 2016 14:52:27 -0600
|
||||
Subject: [PATCH] Fix a crash in process termination when EGL and GLX are both
|
||||
loaded.
|
||||
Date: Tue, 25 Oct 2016 17:32:47 -0600
|
||||
Subject: [PATCH 1/2] GLdispatch: Don't call into the vendor from
|
||||
__glDispatchForceUnpatch.
|
||||
|
||||
Added a new function to libGLdispatch, __glDispatchForceUnpatch, which forces
|
||||
it to unpatch the OpenGL entrypoints before libEGL or libGLX can unload the
|
||||
vendor library that patched them.
|
||||
In __glDispatchForceUnpatch, don't call the vendor's releasePatch callback,
|
||||
because the vendor library might have already been unloaded by that point.
|
||||
---
|
||||
src/GLdispatch/GLdispatch.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
If a vendor patches the OpenGL entrypoints, libGLdispatch doesn't unpatch them
|
||||
when that vendor's context is no longer current, because that adds too much
|
||||
overhead to repeated MakeCurrent+LoseCurrent calls. But, that also means that
|
||||
the patch callbacks end up being dangling pointers after the vendor library is
|
||||
unloaded.
|
||||
diff --git a/src/GLdispatch/GLdispatch.c b/src/GLdispatch/GLdispatch.c
|
||||
index 8c4c3a7..cf4254e 100644
|
||||
--- a/src/GLdispatch/GLdispatch.c
|
||||
+++ b/src/GLdispatch/GLdispatch.c
|
||||
@@ -570,8 +570,10 @@ static int PatchEntrypoints(
|
||||
|
||||
This mainly shows up at process termination when a process loads both libEGL
|
||||
and libGLX, because __glxFini and __eglFini will both call the vendor's
|
||||
threadAttach callback.
|
||||
if (stubCurrentPatchCb) {
|
||||
// Notify the previous vendor that it no longer owns these
|
||||
- // entrypoints.
|
||||
- if (stubCurrentPatchCb->releasePatch != NULL) {
|
||||
+ // entrypoints. If this is being called from a library unload,
|
||||
+ // though, then skip the callback, because the vendor may have
|
||||
+ // already been unloaded.
|
||||
+ if (stubCurrentPatchCb->releasePatch != NULL && !force) {
|
||||
stubCurrentPatchCb->releasePatch();
|
||||
}
|
||||
|
||||
|
||||
From 8146a979d85e975587f3a20f0a6fdc2f04fa478f Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Brenneman <kbrenneman@nvidia.com>
|
||||
Date: Tue, 25 Oct 2016 17:34:26 -0600
|
||||
Subject: [PATCH 2/2] EGL: Don't call into the vendor library from __eglFini.
|
||||
|
||||
In __eglFini, check for a fork, but don't call __glDispatchCheckMultithreaded.
|
||||
|
||||
If a vendor has patched the OpenGL entrypoints, then
|
||||
__glDispatchCheckMultithreaded will try to call the vendor's thread attach
|
||||
callback, but the vendor library may have already been unloaded.
|
||||
|
||||
Fixes https://github.com/NVIDIA/libglvnd/issues/103
|
||||
---
|
||||
src/EGL/libeglvendor.c | 1 +
|
||||
src/GLX/libglxmapping.c | 10 ++++++++++
|
||||
src/GLdispatch/GLdispatch.c | 31 ++++++++++++++++++++++++++++---
|
||||
src/GLdispatch/GLdispatch.h | 9 +++++++++
|
||||
src/GLdispatch/export_list.sym | 1 +
|
||||
5 files changed, 49 insertions(+), 3 deletions(-)
|
||||
src/EGL/libegl.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/EGL/libeglvendor.c b/src/EGL/libeglvendor.c
|
||||
index 3118cca..6d6961a 100644
|
||||
--- a/src/EGL/libeglvendor.c
|
||||
+++ b/src/EGL/libeglvendor.c
|
||||
@@ -144,6 +144,7 @@ void __eglTeardownVendors(void)
|
||||
|
||||
glvnd_list_for_each_entry_safe(vendor, vendorTemp, &__eglVendorList, entry) {
|
||||
glvnd_list_del(&vendor->entry);
|
||||
+ __glDispatchForceUnpatch(vendor->vendorID);
|
||||
TeardownVendor(vendor);
|
||||
}
|
||||
}
|
||||
diff --git a/src/GLX/libglxmapping.c b/src/GLX/libglxmapping.c
|
||||
index 1e83c0b..2e15065 100644
|
||||
--- a/src/GLX/libglxmapping.c
|
||||
+++ b/src/GLX/libglxmapping.c
|
||||
@@ -1026,9 +1026,19 @@ void __glXMappingTeardown(Bool doReset)
|
||||
__glvndPthreadFuncs.rwlock_init(&dpyInfoEntry->info.vendorLock, NULL);
|
||||
}
|
||||
} else {
|
||||
+ __GLXvendorNameHash *pEntry, *tmp;
|
||||
+
|
||||
/* Tear down all hashtables used in this file */
|
||||
__glvndWinsysDispatchCleanup();
|
||||
|
||||
+ // If a GLX vendor library has patched the OpenGL entrypoints, then
|
||||
+ // unpatch them before we unload the vendors.
|
||||
+ LKDHASH_RDLOCK(__glXVendorNameHash);
|
||||
+ HASH_ITER(hh, _LH(__glXVendorNameHash), pEntry, tmp) {
|
||||
+ __glDispatchForceUnpatch(pEntry->vendor.vendorID);
|
||||
+ }
|
||||
+ LKDHASH_UNLOCK(__glXVendorNameHash);
|
||||
+
|
||||
LKDHASH_TEARDOWN(__GLXvendorConfigMappingHash,
|
||||
fbconfigHashtable, NULL, NULL, False);
|
||||
|
||||
diff --git a/src/GLdispatch/GLdispatch.c b/src/GLdispatch/GLdispatch.c
|
||||
index cd0d776..8c4c3a7 100644
|
||||
--- a/src/GLdispatch/GLdispatch.c
|
||||
+++ b/src/GLdispatch/GLdispatch.c
|
||||
@@ -552,13 +552,14 @@ void UnregisterAllStubCallbacks(void)
|
||||
diff --git a/src/EGL/libegl.c b/src/EGL/libegl.c
|
||||
index 65e6605..e0a5488 100644
|
||||
--- a/src/EGL/libegl.c
|
||||
+++ b/src/EGL/libegl.c
|
||||
@@ -1088,7 +1088,7 @@ static void __eglResetOnFork(void);
|
||||
* Currently, this only detects whether a fork occurred since the last
|
||||
* entrypoint was called, and performs recovery as needed.
|
||||
*/
|
||||
static int PatchEntrypoints(
|
||||
const __GLdispatchPatchCallbacks *patchCb,
|
||||
- int vendorID
|
||||
+ int vendorID,
|
||||
+ GLboolean force
|
||||
)
|
||||
-void __eglThreadInitialize(void)
|
||||
+void CheckFork(void)
|
||||
{
|
||||
__GLdispatchStubCallback *stub;
|
||||
CheckDispatchLocked();
|
||||
|
||||
- if (!PatchingIsSafe()) {
|
||||
+ if (!force && !PatchingIsSafe()) {
|
||||
return 0;
|
||||
volatile static int g_threadsInCheck = 0;
|
||||
volatile static int g_lastPid = -1;
|
||||
@@ -1120,7 +1120,11 @@ void __eglThreadInitialize(void)
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
@@ -648,7 +649,7 @@ PUBLIC GLboolean __glDispatchMakeCurrent(__GLdispatchThreadState *threadState,
|
||||
LockDispatch();
|
||||
|
||||
// Patch if necessary
|
||||
- PatchEntrypoints(patchCb, vendorID);
|
||||
+ PatchEntrypoints(patchCb, vendorID, GL_FALSE);
|
||||
|
||||
// If the current entrypoints are unsafe to use with this vendor, bail out.
|
||||
if (!CurrentEntrypointsSafeToUse(vendorID)) {
|
||||
@@ -728,6 +729,30 @@ PUBLIC void __glDispatchLoseCurrent(void)
|
||||
LoseCurrentInternal(curThreadState, GL_FALSE);
|
||||
}
|
||||
|
||||
+PUBLIC GLboolean __glDispatchForceUnpatch(int vendorID)
|
||||
+{
|
||||
+ GLboolean ret = GL_FALSE;
|
||||
+
|
||||
+ LockDispatch();
|
||||
+ if (stubCurrentPatchCb != NULL && stubOwnerVendorID == vendorID) {
|
||||
+ /*
|
||||
+ * The vendor library with the patch callbacks is about to be unloaded,
|
||||
+ * so we need to unpatch the entrypoints even if there's a current
|
||||
+ * context on another thread.
|
||||
+ *
|
||||
+ * If a buggy application is trying to call an OpenGL function on
|
||||
+ * another thread, then we're going to run into problems, but in that
|
||||
+ * case, it's just as likely that the other thread would be somewhere
|
||||
+ * in the vendor library itself.
|
||||
+ */
|
||||
+ PatchEntrypoints(NULL, 0, GL_TRUE);
|
||||
+ ret = GL_TRUE;
|
||||
+ }
|
||||
+ UnlockDispatch();
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
__GLdispatchThreadState *__glDispatchGetCurrentThreadState(void)
|
||||
{
|
||||
return (__GLdispatchThreadState *) __glvndPthreadFuncs.getspecific(threadContextKey);
|
||||
diff --git a/src/GLdispatch/GLdispatch.h b/src/GLdispatch/GLdispatch.h
|
||||
index 3d83215..262a29e 100644
|
||||
--- a/src/GLdispatch/GLdispatch.h
|
||||
+++ b/src/GLdispatch/GLdispatch.h
|
||||
@@ -320,4 +320,13 @@ PUBLIC __GLdispatchThreadState *__glDispatchGetCurrentThreadState(void);
|
||||
*/
|
||||
PUBLIC void __glDispatchCheckMultithreaded(void);
|
||||
|
||||
+/**
|
||||
+ * Tells libGLdispatch to unpatch the OpenGL entrypoints, but only if they were
|
||||
+ * patched by the given vendor.
|
||||
+ *
|
||||
+ * This is called when libEGL or libGLX is unloaded, to remove any dangling
|
||||
+ * pointers to the vendor library's patch callbacks.
|
||||
+ */
|
||||
+PUBLIC GLboolean __glDispatchForceUnpatch(int vendorID);
|
||||
+
|
||||
+void __eglThreadInitialize(void)
|
||||
+{
|
||||
+ CheckFork();
|
||||
__glDispatchCheckMultithreaded();
|
||||
}
|
||||
|
||||
@@ -1190,7 +1194,7 @@ void _fini(void)
|
||||
#endif
|
||||
diff --git a/src/GLdispatch/export_list.sym b/src/GLdispatch/export_list.sym
|
||||
index 41be6bf..a8c1f60 100644
|
||||
--- a/src/GLdispatch/export_list.sym
|
||||
+++ b/src/GLdispatch/export_list.sym
|
||||
@@ -15,3 +15,4 @@ __glDispatchNewVendorID
|
||||
__glDispatchRegisterStubCallbacks
|
||||
__glDispatchReset
|
||||
__glDispatchUnregisterStubCallbacks
|
||||
+__glDispatchForceUnpatch
|
||||
{
|
||||
/* Check for a fork before going further. */
|
||||
- __eglThreadInitialize();
|
||||
+ CheckFork();
|
||||
|
||||
/*
|
||||
* If libEGL owns the current API state, lose current
|
||||
|
@ -1,9 +1,9 @@
|
||||
%global commit0 295e5e5769d0a1db312a76a57870dc8a11742f48
|
||||
%global commit0 28867bb6597d1cf879b12c60a4b512a23758d3f6
|
||||
%global shortcommit0 %(c=%{commit0}; echo ${c:0:7})
|
||||
|
||||
Name: libglvnd
|
||||
Version: 0.2.999
|
||||
Release: 5%{?commit0:.git%{shortcommit0}}%{?dist}
|
||||
Release: 6%{?commit0:.git%{shortcommit0}}%{?dist}
|
||||
Summary: The GL Vendor-Neutral Dispatch library
|
||||
|
||||
License: MIT
|
||||
@ -114,6 +114,10 @@ xvfb-run -a make check V=1 || cat `find . -name test-suite.log`
|
||||
|
||||
|
||||
%changelog
|
||||
* Wed Oct 26 2016 Leigh Scott <leigh123linux@googlemail.com> - 0.2.999-6.git28867bb
|
||||
- Update snapshot
|
||||
- Fix EGL crash for KDE/Plasma (rfbz#4303)
|
||||
|
||||
* Tue Oct 25 2016 Leigh Scott <leigh123linux@googlemail.com> - 0.2.999-5.git295e5e5
|
||||
- Fix EGL crash (rfbz#4303)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user