Unity Editor Crash - Segmentation Fault near FMOD::Studio::System::release()

After adding FMOD to our Unity project we’ve been getting fairly frequent full program crashes due to segmentation faults. I haven’t been able to track down exactly how to reproduce the issue, but I have noticed that when it happens it’s during an assembly/domain reload, right after “Destroying editor system instance” based on the editor logs. There is a chance this is due to some extra scripting I’ve done, but I’m also getting some of the crashes when I revert to before I made any changes via version control. Any ideas on where to investigate would be very appreciated! More details below:

Versions:
Unity: 2020.3.8f1
FMOD Studio Unity Integration: 2.02.01

Apple Crash Report:
In particular, this is the section pointing me toward FMOD (in addition to this only happening after we added FMOD to the project)

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   Unity [47930]

VM Regions Near 0x7f8bc1f01858:
    MALLOC_LARGE             7f8bc1eb4000-7f8bc1ec7000 [   76K] rw-/rwx SM=PRV  
--> 
    MALLOC_LARGE             7f8bc1f04000-7f8bc1f2f000 [  172K] rw-/rwx SM=PRV  

Thread 0 Crashed:: tid_307  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fff20481fde __kill + 10
1   libmonobdwgc-2.0.dylib        	0x000000016bf9ed64 mono_chain_signal + 79
2   libmonobdwgc-2.0.dylib        	0x000000016be8ddf5 mono_sigsegv_signal_handler + 443
3   libsystem_platform.dylib      	0x00007fff204f4d7d _sigtramp + 29
4   ???                           	000000000000000000 0 + 0
5   com.fmod.fmodstudioL          	0x00000001f2c6061c 0x1f2a40000 + 2229788
6   com.fmod.fmodstudioL          	0x00000001f2c62100 0x1f2a40000 + 2236672
7   com.fmod.fmodstudioL          	0x00000001f2c6200f 0x1f2a40000 + 2236431
8   com.fmod.fmodstudioL          	0x00000001f2c58453 FMOD::System::release() + 87
9   com.fmod.fmodstudioL          	0x00000001f2a573e4 0x1f2a40000 + 95204
10  com.fmod.fmodstudioL          	0x00000001f2a576c7 0x1f2a40000 + 95943
11  com.fmod.fmodstudioL          	0x00000001f2b7e23b FMOD::Studio::System::release() + 417
12  ???                           	0x000000022a823c5d 0 + 9303112797

Unity Editor Log:

Start importing Assets/Plugins/FMOD/src/Settings.cs using Guid(eef8d824ea7b63742966aaa0e94ac383) Importer(-1,00000000000000000000000000000000)  -> (artifact id: '555e703788758b5cd0d56d513ec74310') in 0.021721 seconds
AssetDatabase: script compilation time: 0.092287s
- Starting script compilation
- Starting compile Library/ScriptAssemblies/FMODUnity.dll
Deleting stamp file at Library/ScriptAssemblies/BuiltinAssemblies.stamp
- Finished compile Library/ScriptAssemblies/FMODUnity.dll in 2.615378 seconds
- Skipping compile Library/ScriptAssemblies/FMODUnityEditor.dll because all references are unchanged
- Skipping compile Library/ScriptAssemblies/FMODUnityResonance.dll because all references are unchanged
- Skipping compile Library/ScriptAssemblies/FMODUnityResonanceEditor.dll because all references are unchanged
- Skipping compile Library/ScriptAssemblies/Assembly-CSharp.dll because all references are unchanged
- Skipping compile Library/ScriptAssemblies/Assembly-CSharp-Editor.dll because all references are unchanged
- Finished script compilation in 2.775349 seconds
Reloading assemblies after forced synchronous recompile.
Begin MonoManager ReloadAssembly
FMOD Studio: Destroying editor system instance
UnityEngine.StackTraceUtility:ExtractStackTrace () (at /Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/StackTrace.cs:37)
UnityEngine.DebugLogHandler:LogFormat (UnityEngine.LogType,UnityEngine.Object,string,object[])
UnityEngine.Logger:Log (UnityEngine.LogType,object)
UnityEngine.Debug:Log (object)
FMODUnity.EditorUtils:DestroySystem () (at Assets/Plugins/FMOD/src/Editor/EditorUtils.cs:396)
FMODUnity.EditorUtils:HandleBeforeAssemblyReload () (at Assets/Plugins/FMOD/src/Editor/EditorUtils.cs:341)
UnityEditor.AssemblyReloadEvents:OnBeforeAssemblyReload () (at /Users/bokken/buildslave/unity/build/Editor/Mono/AssemblyReloadEvents.cs:15)

(Filename: Assets/Plugins/FMOD/src/Editor/EditorUtils.cs Line: 396)

Obtained 256 stack frames.
#0  0x000001f2c53cf1 in FMOD::SoundGroup::getUserData(void**)
#1  0x000001f2c6061c in FMOD::SystemI::createClientProfile()
#2  0x000001f2c62100 in FMOD::SystemI::setInternalCallback(int, FMOD_RESULT (*)(FMOD_SYSTEM*, unsigned int, void*, void*, void*), void*)
#3  0x000001f2c6200f in FMOD::SystemI::setInternalCallback(int, FMOD_RESULT (*)(FMOD_SYSTEM*, unsigned int, void*, void*, void*), void*)
#4  0x000001f2c58453 in FMOD::System::release()
#5  0x000001f2a573e4 in (null)
#6  0x000001f2a576c7 in (null)
#7  0x000001f2b7e23b in FMOD::Studio::System::release()
#8  0x0000022a823c5d in  (wrapper managed-to-native) FMOD.Studio.System:FMOD_Studio_System_Release (intptr) {0x7f8bbdd1c698} + 0x5d (0x22a823c00 0x22a823ce5) [0x161042960 - Unity Child Domain]
#9  0x00000000000000 in (Unknown)
#10 0x00000000000000 in (Unknown)
#11 0x007f8bc60ad838 in (Unknown)
...

My changes:
Finally, the only changes I’ve made are in EditorUtils.cs where I’ve hacked in the ability to play programmer sounds, very similar to what is done in the dialogue and audio tables example:

public static void PreviewEvent(EditorEventRef eventRef, Dictionary<string, float> previewParamValues, string key = "")
        {
            ...
                    PreviewUpdateParameter(param.ID, previewParamValues[param.Name]);
                }
            }

            if (!string.IsNullOrEmpty(key)) {
                var dialogueCallback = new FMOD.Studio.EVENT_CALLBACK(DialogueEventCallback);
                GCHandle stringHandle = GCHandle.Alloc(key, GCHandleType.Pinned);
                previewEventInstance.setUserData(GCHandle.ToIntPtr(stringHandle));
                previewEventInstance.setCallback(dialogueCallback);
            }

            CheckResult(previewEventInstance.start());
            previewEventInstance.release();
            previewState = PreviewState.Playing;
        }

        [AOT.MonoPInvokeCallback (typeof (FMOD.Studio.EVENT_CALLBACK))]
        static FMOD.RESULT DialogueEventCallback(FMOD.Studio.EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
        {
            // Retrieve the user data
            IntPtr stringPtr;

            FMOD.Studio.EventInstance instance = new FMOD.Studio.EventInstance(instancePtr);
            instance.getUserData(out stringPtr);

            // Get the string object
            GCHandle stringHandle = GCHandle.FromIntPtr(stringPtr);
            String key = stringHandle.Target as String;

            switch (type)
            {
                case FMOD.Studio.EVENT_CALLBACK_TYPE.CREATE_PROGRAMMER_SOUND:
                    {
                        FMOD.MODE soundMode = FMOD.MODE.LOOP_NORMAL | FMOD.MODE.CREATECOMPRESSEDSAMPLE | FMOD.MODE.NONBLOCKING;
                        var parameter = (FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));

                            FMOD.Studio.SOUND_INFO dialogueSoundInfo;
                            var keyResult = FMODUnity.RuntimeManager.StudioSystem.getSoundInfo(key, out dialogueSoundInfo);
                            if (keyResult != FMOD.RESULT.OK)
                            {
                                break;
                            }
                            FMOD.Sound dialogueSound;
                            var soundResult = FMODUnity.RuntimeManager.CoreSystem.createSound(dialogueSoundInfo.name_or_data, soundMode | dialogueSoundInfo.mode, ref dialogueSoundInfo.exinfo, out dialogueSound);
                            if (soundResult == FMOD.RESULT.OK)
                            {
                                parameter.sound = dialogueSound.handle;
                                parameter.subsoundIndex = dialogueSoundInfo.subsoundindex;
                                Marshal.StructureToPtr(parameter, parameterPtr, false);
                            }
                    }
                    break;
                case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROY_PROGRAMMER_SOUND:
                    {
                        var parameter = (FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(FMOD.Studio.PROGRAMMER_SOUND_PROPERTIES));
                        var sound = new FMOD.Sound();
                        sound.handle = parameter.sound;
                        sound.release();
                        sound.clearHandle();

                    }
                    break;
                case FMOD.Studio.EVENT_CALLBACK_TYPE.DESTROYED:
                    // Now the event has been destroyed, unpin the string memory so it can be garbage collected
                    stringHandle.Free();
                    break;
            }
            return FMOD.RESULT.OK;
        }

Like I said, any suggestions of what to look for or investigate would be very appreciated!

I managed to get a segfault using the code you provided, though I am not sure yet how to recreate it reliably. The crash at FMOD::System::release() might be due to unneccessarily calling release on previewEventInstance, which is already being handled in PreviewStop().
Other things I can think of are that you aren’t saving your callback in a member so there’s a chance it’s getting garbage collected.
Are you getting any other errors in the unity console?
If you haven’t already done so, you could try enabling API Error Logging in the FMOD Settings as well as switching the logging level to “Log”, and see if that provides any more clues next time it crashes.