mirror of
https://github.com/Facepunch/sbox-public.git
synced 2026-02-07 13:11:07 -05:00
Speculative fix for the EnqueueResourceManifest crash reported on Sentry. The crash occurs in a thread-interlocked compare-exchange operation: ``` ThreadInterlockedCompareExchange64 ThreadInterlockedCompareExchangePointer CTSQueue<T>::InterlockedCompareExchangeNode CTSQueue<T>::Push CTSQueue<T>::PushItem CResourceSystem::EnqueueResourceManifest CResourceSystem::CreateResourceManifestInternal Exports::g_pRsrcSystm_LoadResourceInManifest ``` The most likely cause of a ThreadInterlock failure is a null pointer. AFAIK the resource queue only becomes null during shutdown, so this crash is probably a race condition where managed code attempts to load a resource while the engine is shutting down.
65 lines
1.4 KiB
C#
65 lines
1.4 KiB
C#
using System.Threading;
|
|
|
|
namespace Sandbox;
|
|
|
|
//
|
|
// This is just a test right now
|
|
//
|
|
class AsyncResourceLoader : IDisposable
|
|
{
|
|
HResourceManifest manifest;
|
|
|
|
AsyncResourceLoader( HResourceManifest manifest )
|
|
{
|
|
this.manifest = manifest;
|
|
}
|
|
|
|
~AsyncResourceLoader()
|
|
{
|
|
if ( manifest.IsValid && !NativeEngine.g_pResourceSystem.IsShuttingDown() )
|
|
{
|
|
MainThread.QueueDispose( this );
|
|
}
|
|
}
|
|
|
|
public async Task WaitForLoad( CancellationToken token = default )
|
|
{
|
|
// does this shit itself if the resource is missing?
|
|
// does it handle compiling okay?
|
|
while ( !NativeEngine.g_pResourceSystem.IsShuttingDown() && !NativeEngine.g_pResourceSystem.IsManifestLoaded( manifest ) )
|
|
{
|
|
await Task.Yield();
|
|
token.ThrowIfCancellationRequested();
|
|
|
|
if ( NativeEngine.g_pResourceSystem.IsShuttingDown() )
|
|
return;
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if ( manifest.IsValid && !NativeEngine.g_pResourceSystem.IsShuttingDown() )
|
|
{
|
|
ThreadSafe.AssertIsMainThread();
|
|
|
|
NativeEngine.g_pResourceSystem.DestroyResourceManifest( manifest );
|
|
}
|
|
|
|
manifest = default;
|
|
GC.SuppressFinalize( this );
|
|
}
|
|
|
|
static public AsyncResourceLoader Load( string filename )
|
|
{
|
|
ThreadSafe.AssertIsMainThread();
|
|
|
|
if ( NativeEngine.g_pResourceSystem.IsShuttingDown() )
|
|
return default;
|
|
|
|
var manifest = NativeEngine.g_pResourceSystem.LoadResourceInManifest( filename );
|
|
if ( manifest.IsNull ) return default;
|
|
|
|
return new AsyncResourceLoader( manifest );
|
|
}
|
|
}
|