Attempt to workaround odd crashes in glslang.

I accidentally managed to reproduce an issue which has been plaguing
users for a while, where glslang throws an assert after closing a game
(and starting a new one).

pthread_setspecific was somehow failing with an EINVAL call, despite the
key never having been freed. I suspect some kind of corruption happening
when dynamic libraries are unloaded, but I doubt this is a bug in either
RetroArch or glslang per-se.

My workaround here is to tear down all TLS use in glslang after we're
done compiling. Somehow this works around the problem for me, and I
don't really see another viable fix. Valgrind does not say anything about the
issue, so doubt it's memory corruption either.

I had to fix a minor TLS leak in glslang as DetachProcess does not free
the PoolIndex TLS.
This commit is contained in:
Hans-Kristian Arntzen 2019-12-16 16:47:58 +01:00 committed by twinaphex
parent 3cfed7ba01
commit 4437cd1eac
5 changed files with 33 additions and 4 deletions

View File

@ -21,6 +21,7 @@
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <mutex>
#include "../../verbosity.h"
@ -31,18 +32,33 @@ struct SlangProcess
{
public:
SlangProcess();
TBuiltInResource& GetResources() { return Resources; }
~SlangProcess() { FinalizeProcess(); }
private:
TBuiltInResource Resources;
};
// We don't use glslang from multiple threads, but to be sure.
// Initializing TLS and freeing it for glslang works around a really bizarre issue
// where the TLS key is suddenly corrupted *somehow*.
static std::mutex glslang_global_lock;
struct SlangProcessHolder
{
SlangProcessHolder()
{
glslang_global_lock.lock();
InitializeProcess();
}
~SlangProcessHolder()
{
FinalizeProcess();
glslang_global_lock.unlock();
}
};
SlangProcess::SlangProcess()
{
InitializeProcess();
char DefaultConfig[] =
"MaxLights 32\n"
"MaxClipPlanes 6\n"
@ -337,6 +353,7 @@ SlangProcess::SlangProcess()
bool glslang::compile_spirv(const string &source, Stage stage, std::vector<uint32_t> *spirv)
{
static SlangProcess process;
SlangProcessHolder process_holder;
TProgram program;
EShLanguage language;

View File

@ -158,6 +158,7 @@ bool DetachProcess()
OS_FreeTLSIndex(ThreadInitializeIndex);
ThreadInitializeIndex = OS_INVALID_TLS_INDEX;
DeinitializePoolIndex();
return success;
}

View File

@ -38,6 +38,7 @@
namespace glslang {
bool InitializePoolIndex();
bool DeinitializePoolIndex();
} // end namespace glslang

View File

@ -65,6 +65,15 @@ bool InitializePoolIndex()
return true;
}
bool DeinitializePoolIndex()
{
if (PoolIndex == OS_INVALID_TLS_INDEX)
return false;
OS_FreeTLSIndex(PoolIndex);
PoolIndex = OS_INVALID_TLS_INDEX;
return true;
}
//
// Implement the functionality of the TPoolAllocator class, which
// is documented in PoolAlloc.h.

View File

@ -1312,6 +1312,7 @@ int __fastcall ShFinalize()
glslang::HlslScanContext::deleteKeywordMap();
#endif
DetachProcess();
return 1;
}