Fix EGL crash (rfbz#4303)
This commit is contained in:
parent
fa9c878a75
commit
2e09c839ae
153
egl_crash.patch
Normal file
153
egl_crash.patch
Normal file
@ -0,0 +1,153 @@
|
||||
From 61bd107cc64f158d7a3e40877c47aa565651487a 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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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(-)
|
||||
|
||||
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)
|
||||
*/
|
||||
static int PatchEntrypoints(
|
||||
const __GLdispatchPatchCallbacks *patchCb,
|
||||
- int vendorID
|
||||
+ int vendorID,
|
||||
+ GLboolean force
|
||||
)
|
||||
{
|
||||
__GLdispatchStubCallback *stub;
|
||||
CheckDispatchLocked();
|
||||
|
||||
- if (!PatchingIsSafe()) {
|
||||
+ if (!force && !PatchingIsSafe()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
+
|
||||
#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
|
@ -3,12 +3,13 @@
|
||||
|
||||
Name: libglvnd
|
||||
Version: 0.2.999
|
||||
Release: 4%{?commit0:.git%{shortcommit0}}%{?dist}
|
||||
Release: 5%{?commit0:.git%{shortcommit0}}%{?dist}
|
||||
Summary: The GL Vendor-Neutral Dispatch library
|
||||
|
||||
License: MIT
|
||||
URL: https://github.com/NVIDIA/libglvnd
|
||||
Source0: https://github.com/NVIDIA/%{name}/archive/%{commit0}.tar.gz#/%{name}-%{shortcommit0}.tar.gz
|
||||
Patch0: egl_crash.patch
|
||||
|
||||
BuildRequires: libtool
|
||||
BuildRequires: gcc
|
||||
@ -43,7 +44,7 @@ developing applications that use %{name}.
|
||||
|
||||
|
||||
%prep
|
||||
%autosetup -n %{name}-%{?commit0}%{?!commit0:%{version}}
|
||||
%autosetup -p1 -n %{name}-%{?commit0}%{?!commit0:%{version}}
|
||||
autoreconf -vif
|
||||
|
||||
%build
|
||||
@ -113,6 +114,9 @@ xvfb-run -a make check V=1 || cat `find . -name test-suite.log`
|
||||
|
||||
|
||||
%changelog
|
||||
* Tue Oct 25 2016 Leigh Scott <leigh123linux@googlemail.com> - 0.2.999-5.git295e5e5
|
||||
- Fix EGL crash (rfbz#4303)
|
||||
|
||||
* Fri Oct 14 2016 Nicolas Chauvet <kwizart@gmail.com> - 0.2.999-4.git295e5e5
|
||||
- Update snapshot
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user