diff --git a/egl_crash.patch b/egl_crash.patch index 3e2e882..b5754fb 100644 --- a/egl_crash.patch +++ b/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 -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( + + 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(); + } + -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. +From 8146a979d85e975587f3a20f0a6fdc2f04fa478f Mon Sep 17 00:00:00 2001 +From: Kyle Brenneman +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); +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. + */ +-void __eglThreadInitialize(void) ++void CheckFork(void) + { + volatile static int g_threadsInCheck = 0; + volatile static int g_lastPid = -1; +@@ -1120,7 +1120,11 @@ void __eglThreadInitialize(void) + sched_yield(); } - } 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); ++void __eglThreadInitialize(void) ++{ ++ CheckFork(); + __glDispatchCheckMultithreaded(); } -+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); -+ +@@ -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 diff --git a/libglvnd.spec b/libglvnd.spec index f0f10ef..261a941 100644 --- a/libglvnd.spec +++ b/libglvnd.spec @@ -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 - 0.2.999-6.git28867bb +- Update snapshot +- Fix EGL crash for KDE/Plasma (rfbz#4303) + * Tue Oct 25 2016 Leigh Scott - 0.2.999-5.git295e5e5 - Fix EGL crash (rfbz#4303) diff --git a/sources b/sources index 69cdbc8..99bd5a7 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -1443c2891d9a2c3792002f116ea77047 libglvnd-295e5e5.tar.gz +7f361721ca9b1db26ebb40400034c45f libglvnd-28867bb.tar.gz