Placeholder-Software / Dissonance

Unity Voice Chat Asset
69 stars 5 forks source link

[bug] ArgumentException: GCHandle value belongs to a different domain #286

Open ximael opened 3 months ago

ximael commented 3 months ago

I have Main Menu scene and Game scene. In the Game scene I've added Dissonance prefab (you can see its settings here)

1) Start network game (one client is host) 2) Host quits the game (to menu or the app itself) 3) Clients are disconnected and are trying to load the main menu 4) The game freezes and this error in the log.

This happens not every time, maybe 25%. I suppose, something with the GC.

Unity 2022.3.7f1 LTS Netcode for gameobjects Facepunch transport Dissonance with fmod playback and recording

Error text in the log: Unloading 5 Unused Serialized files (Serialized files now loaded: 4) ArgumentException: GCHandle value belongs to a different domain at System.Runtime.InteropServices.GCHandle.op_Explicit (System.IntPtr value) [0x00020] in :0 at System.Runtime.InteropServices.GCHandle.FromIntPtr (System.IntPtr value) [0x00000] in :0 at Dissonance.Integrations.FMOD_Playback.FMODVoicePlayback.ShouldProcessDSP (FMOD.DSP_STATE& dsp_state, System.Boolean inputsidle, System.UInt32 length, FMOD.CHANNELMASK inmask, System.Int32 inchannels, FMOD.SPEAKERMODE speakermode) [0x0003a] in F:\Git\TavernCoop\Assets\Packages\Dissonance\Integrations\FMOD_Playback\FMODVoicePlayback.cs:270 at (wrapper native-to-managed) Dissonance.Integrations.FMOD_Playback.FMODVoicePlayback.ShouldProcessDSP(FMOD.DSP_STATE&,int,uint,FMOD.CHANNELMASK,int,FMOD.SPEAKERMODE) UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object) UnityEngine.DebugLogHandler:LogException(Exception, Object) UnityEngine.Logger:LogException(Exception, Object) UnityEngine.Debug:LogException(Exception) UnityEngine.<>c:b__0_0(Object, UnhandledExceptionEventArgs) (at C:\build\output\unity\unity\Runtime\Export\Scripting\UnhandledExceptionHandler.bindings.cs:46)

(Filename: F:/Git/TavernCoop/Assets/Packages/Dissonance/Integrations/FMOD_Playback/FMODVoicePlayback.cs Line: 270)

And right after the error: UnloadTime: 140.743600 ms Unloading 1632 unused Assets / (0.66 GB). Loaded Objects now: 205304. Memory consumption went from 2.24 GB to 1.58 GB. Total: 159.469400 ms (FindLiveObjects: 12.092000 ms CreateObjectMapping: 13.194300 ms MarkObjects: 32.183300 ms DeleteObjects: 101.999200 ms)

//End of the log file

FMODVoicePlayback.cs Line: 270: var ud = GCHandle.FromIntPtr(userdata);

martindevans commented 3 months ago

This looks like it might be an editor only issue - can you confirm if this happens in player builds?

ximael commented 3 months ago

It happend in the player build (win, mono, .NET Framework). I'm trying to reproduce it on one pc, but no luck yet.

alexonskull commented 3 weeks ago

Can confirm that this happens in build too. Exact same situation, Dissonance, Steamworks + Fmod. Host leaves, clients disconnect and try to load menu scene. Some succeed others crash and this is the last log.

martindevans commented 3 weeks ago

It looks like this might happen if the GCHandle is left set as the "user data" in FMOD. As far as I can tell FMOD makes a callback even after it has been stopped, however that callback is now trying to access resources that were disposed in the scene transition and causes this error.

To handle this, could you try making the following changes:

In Teardown() (line 99):

if (_channel.hasHandle())
{
    _channel.stop();
    _channel.setUserData(IntPtr.Zero); // <---- Add this
    _channel.removeDSP(_dsp);
    _channel.clearHandle();
}

 if (_dsp.hasHandle())
{
    _dsp.setUserData(IntPtr.Zero); // <---- Add this
    _dsp.release();
    _dsp.clearHandle();
}

In ChannelEventCallback (line 217):

if (!Check(channel.getUserData(out var userdata), "Failed to getUserData from channel"))
    return RESULT.OK;

if (userdata == IntPtr.Zero)
    return RESULT.OK; // <---- Add this

In ReadDSP (line 242):

if (gudResult != RESULT.OK || userdata == IntPtr.Zero) // <---- Add this final check into existing if statement
{

In ShouldProcessDSP (line 261):

if (gudResult != RESULT.OK || userdata == IntPtr.Zero) // <---- Add this final check into existing if statement
    return RESULT.OK;

The first change should clear the invalid GCHandle from FMOD when it is destroyed. The rest of the changes add checks in everywhere that FMOD might try to use that invalid value, simply early exiting from the callback.

martindevans commented 3 weeks ago

Note: If these changes work for you please tell me and I will incorporate them into the package :)

alexonskull commented 3 weeks ago

Thank you! Implemented them now, I will run a few tests and let you know!

alexonskull commented 2 weeks ago

Crash hasn't happened since, I did a bit of forced testing, loading and unloading the same game instance, as well as a lot of regular game testing we did. Seems to have been fixed.

martindevans commented 2 weeks ago

Thanks for testing that. I'll include these changes in an update to the main package soon.