Unity Editor crash on play mode exit

Hello, we struggled with some problem on unity play mode exit while trying to delete channels. Normal cleaning up (delete channels and continue playing) is ok.

  1. vivox ver: com.unity.services.vivox-15.1.170000
  2. Unity ver: 2020.3.26f1
  3. Build target: Android

Crash log:

Stacktrace:

at <unknown> <0xffffffff>
at (wrapper managed-to-native) VivoxCoreInstancePINVOKE.vx_req_sessiongroup_remove_session_t_session_handle_set (System.Runtime.InteropServices.HandleRef,string) [0x0001b] in <5437eccd060948ef9868f0cf9dbf3609>:0
at vx_req_sessiongroup_remove_session_t.set_session_handle (string) [0x00001] in E:\UnityProjects\drive-zone\Library\PackageCache\com.unity.services.vivox@c9c00ead863c-1649177403252\Runtime\VivoxUnity\swig\vx_req_sessiongroup_remove_session_t.cs:63
at VivoxUnity.Private.ChannelSession.Disconnect (System.AsyncCallback) [0x0005d] in E:\UnityProjects\drive-zone\Library\PackageCache\com.unity.services.vivox@c9c00ead863c-1649177403252\Runtime\VivoxUnity\Private\ChannelSession.cs:397
at VivoxUnity.Private.LoginSession.WaitDeleteChannelSession (VivoxUnity.ChannelId) [0x00001] in E:\UnityProjects\drive-zone\Library\PackageCache\com.unity.services.vivox@c9c00ead863c-1649177403252\Runtime\VivoxUnity\Private\LoginSession.cs:1242
at VivoxUnity.Private.LoginSession.DeleteChannelSession (VivoxUnity.ChannelId) [0x00057] in E:\UnityProjects\drive-zone\Library\PackageCache\com.unity.services.vivox@c9c00ead863c-1649177403252\Runtime\VivoxUnity\Private\LoginSession.cs:564
at Core.VoiceChat.VivoxVoiceServiceImpl.CleanUp () [0x000ba] in E:\UnityProjects\drive-zone\Assets\Scripts\Services\VoiceSystem\VivoxImplementation\VivoxVoiceServiceImpl.cs:469
at Core.VoiceChat.VivoxVoiceServiceImpl.Dispose () [0x00001] in E:\UnityProjects\drive-zone\Assets\Scripts\Services\VoiceSystem\VivoxImplementation\VivoxVoiceServiceImpl.cs:589
at BehaviourInject.Internal.SingleAutocomposeDependency.Dispose () [0x00015] in E:\UnityProjects\drive-zone\Assets\BInject\Scripts\BehaviourInject\IDependency.cs:80
at BehaviourInject.Context.DisposeDependencies () [0x00007] in E:\UnityProjects\drive-zone\Assets\BInject\Scripts\BehaviourInject\Context.cs:520
at BehaviourInject.Context.Destroy () [0x00023] in E:\UnityProjects\drive-zone\Assets\BInject\Scripts\BehaviourInject\Context.cs:495
at Contexts.ApplicationContext.OnDestroy () [0x00001] in E:\UnityProjects\drive-zone\Assets\Scripts\Contexts\ApplicationContext.cs:119
at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x00020] in <695d1cc93cca45069c528c15c9fdd749>:0

Up

I am sorry to hear you are experiencing a crash! I have some followup questions to help analyze your issue:

  • Is this only occurring on Android? Or are you seeing this on other platforms as well?
  • Would you be able to provide a snippet of your code where you are deleting channels? (please ensure your issuer and key are NOT included in the snippet)
  • Where in the process are you deleting channels? Can you describe the flow of your implementation.

Hi, I’d just like to chime in to say that we are seeing the same issue and I was happy to see this post and that it therefore isn’t just us.

It happens 100% of the time for us when we leave Play mode (we’ve had to add a developer option to disable Vivox entirely as it’s obviously impeding our workflow).

Our stacktrace is the following (I had to remove some parts for NDA reasons):

=================================================================
    Managed Stacktrace:
=================================================================
      at <unknown> <0xffffffff>
      at VivoxCoreInstancePINVOKE:vx_req_sessiongroup_remove_session_t_session_handle_set <0x0011b>
      at vx_req_sessiongroup_remove_session_t:set_session_handle <0x000ca>
      at VivoxUnity.Private.ChannelSession:smile:isconnect <0x0056a>
      [SNIP]
      at PlayerVoice:OnDestroy <0x000aa>
      at System.Object:runtime_invoke_void__this__ <0x00187>
=================================================================
Received signal SIGSEGV
Obtained 30 stack frames
0x000002448817149c (Mono JIT Code) (wrapper managed-to-native) VivoxCoreInstancePINVOKE:vx_req_sessiongroup_remove_session_t_session_handle_set (System.Runtime.InteropServices.HandleRef,string)
0x00000244881712fb (Mono JIT Code) [vx_req_sessiongroup_remove_session_t.cs:63] vx_req_sessiongroup_remove_session_t:set_session_handle (string)
0x000002448817056b (Mono JIT Code) [ChannelSession.cs:403] VivoxUnity.Private.ChannelSession:smile:isconnect (System.AsyncCallback)
[SNIP]
0x000002448816f53b (Mono JIT Code) [PlayerVoice.cs:35] PlayerVoice:OnDestroy ()
0x00000244118f4518 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007fff058ae0a4 (mono-2.0-bdwgc) [mini-runtime.c:3445] mono_jit_runtime_invoke
0x00007fff057ee744 (mono-2.0-bdwgc) [object.c:3066] do_runtime_invoke
0x00007fff057ee8dc (mono-2.0-bdwgc) [object.c:3113] mono_runtime_invoke
0x00007ff6a0fff454 (Unity) scripting_method_invoke
0x00007ff6a0ffa074 (Unity) ScriptingInvocation::Invoke
0x00007ff6a0ffa15e (Unity) ScriptingInvocation::InvokeChecked
0x00007ff6a1073ff6 (Unity) SerializableManagedRef::CallMethod
0x00007ff6a0fd8f56 (Unity) MonoBehaviour::WillDestroyComponent
0x00007ff6a09a1d01 (Unity) GameObject::WillDestroyGameObject
0x00007ff6a0cac731 (Unity) PreDestroyRecursive
0x00007ff6a0caa757 (Unity) DestroyObjectHighLevel_Internal
0x00007ff6a0caa394 (Unity) DestroyObjectHighLevel
0x00007ff6a0cb4cde (Unity) DestroyWorldObjects
0x00007ff6a1ee1da1 (Unity) EditorSceneManager::RestoreSceneBackups
0x00007ff6a1bf3aed (Unity) PlayerLoopController::ExitPlayMode
0x00007ff6a1c02b41 (Unity) PlayerLoopController::SetIsPlaying
0x00007ff6a1c05f3d (Unity) Application::TickTimer
0x00007ff6a204e10a (Unity) MainMessageLoop
0x00007ff6a20529db (Unity) WinMain
0x00007ff6a337427e (Unity) __scrt_common_main_seh
0x00007fff907954e0 (KERNEL32) BaseThreadInitThunk
0x00007fff9142485b (ntdll) RtlUserThreadStart

Again, this happens any time we hit exit out of play mode in the editor when we are connected to a channel.

Can you advise on what we can do to avoid this?

  1. It is happening in edtior. It happens 100% of the time for us when we leave Play mode.

List<ChannelId> channelsToDelete = new List<ChannelId>();

            foreach (var channelId in _loginSession.ChannelSessions.Keys)
            {
                channelsToDelete.Add(channelId);
            }

            for (int i = 0; i < channelsToDelete.Count; i++)
            {
                var id = channelsToDelete[i];

                var session = _loginSession.GetChannelSession(id);

                if (session != null)
                {
                    _loginSession.DeleteChannelSession(id);
                }
            }
  1. It is happening on Gameobject context holder destruction

Thank you for the additional information! We are actively investigating possible causes for this issue and trying to reproduce in house.

One more follow up question, what platform are you using for your editor? PC, Windows, Linux etc?

PC Windows editor

Hello, just wanted to confirm that we’re also experiencing same issue. Once we login to vivox, if we exit play mode without firstly

  • logging out,
  • cleaning up client and
  • uninitializing vivox

unity editor crashes. Using unity 2020.3.27 in windows and vivox 15.1.180000-pre.1 (currently latest version)

Haven’t tested yet on android or other platforms.

Thank you both for the additional information. We will retest on our end and keep you posted on our investigation. Thank you for your cooperation, and I will come back with updates soon!

Hello. Any information for us?

@Neozman , we have not been able to replicate yet.

@tinto22 , what editor and Vivox versions are you using?

@K97 , do you need to perform all three steps to prevent crash or is logging out enough?

@Neozman @tinto22 @K97 Although we have not been able to replicate this, can you please try adding the following code to your projects. Please adjust as needed based on what you have named your Vivox Client object (in this code, the Client is declared as _client).

private void OnApplicationQuit()
{
    Client.Cleanup();
    if (_client != null)
    {
        VivoxLog("Uninitializing client.");
        _client.Uninitialize();
    }
}

This code comes from our VivoxVoiceManager that you can see in our ChatChannelSample. It provides the MonoBehaviour handling of OnApplicationQuit(), which is also called when the editor leaves play mode. We use it to cleanup and uninitialize the Vivox client for the sample.

Unfortunalty, the last version of Vivox still has this problem.

@dylan_unity3d , we have the same clean up code inside. The problem is that we are trying to disconnect connected channel on exit from playmode

Temporary solved this problem by adding async channel disconnection and saving application quit flag so if disconnection proccess detect if game is exiting than interrupt disconnection. I’ve left it only in editor

Same here. Vivox 15.1.180001-pre.2, Unity 2020.3.26f1 (also tried 2020.3.36f1 and 2021.3.5f1), PC Windows Editor

Stacktrace:

  at <unknown> <0xffffffff>
  at (wrapper managed-to-native) VivoxCoreInstancePINVOKE.vx_req_sessiongroup_remove_session_t_session_handle_set (System.Runtime.InteropServices.HandleRef,string) [0x0001b] in <eb812ede3c3f41b6abd899e76eac7407>:0
  at vx_req_sessiongroup_remove_session_t.set_session_handle (string) [0x00001] in W:\work\unity\sb-win\quantum_unity\Library\PackageCache\com.unity.services.vivox@15.1.180001-pre.2\Runtime\VivoxUnity\swig\vx_req_sessiongroup_remove_session_t.cs:63
  at VivoxUnity.Private.ChannelSession.Disconnect (System.AsyncCallback) [0x0005d] in W:\work\unity\sb-win\quantum_unity\Library\PackageCache\com.unity.services.vivox@15.1.180001-pre.2\Runtime\VivoxUnity\Private\ChannelSession.cs:422
  at Game.code.control.vivox.VivoxAPI/Channel/<>c__DisplayClass10_0.<leave>b__0 (System.AsyncCallback) [0x00000] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\vivox\VivoxAPI.Channel.transformed.cs:148
  at Game.code.control.vivox.VivoxAPI.callbackToFuture (System.Action`1<System.AsyncCallback>,System.Action`1<System.IAsyncResult>) [0x0001a] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\vivox\VivoxAPI.transformed.cs:163
  at Game.code.control.vivox.VivoxAPI/Channel.leave (bool) [0x000c9] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\vivox\VivoxAPI.Channel.transformed.cs:148
  at Game.code.control.GameController/Init/<>c__DisplayClass135_15.<.ctor>g__leaveCurrentVivoxChannel|116 () [0x00060] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameController.Init.transformed.cs:807
  at FPCSharpUnity.core.reactive.Subscription.unsubscribe () [0x0000f] in W:\work\unity\sb-win\quantum_code\FPCSharpUnity.core\reactive\Subscription.cs:48
  at FPCSharpUnity.core.reactive.Subscription.Dispose () [0x00000] in W:\work\unity\sb-win\quantum_code\FPCSharpUnity.core\reactive\Subscription.cs:58
  at FPCSharpUnity.core.dispose.DisposableTracker.Dispose () [0x000a9] in W:\work\unity\sb-win\quantum_code\FPCSharpUnity.core\dispose\DisposableTracker.cs:120
  at Game.code.control.GameController/Init.dispose (bool) [0x00096] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameController.Init.transformed.cs:885
  at Game.code.control.GameController/Init.Dispose () [0x00001] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameController.Init.transformed.cs:872
  at Game.code.control.GameInitController.disposeLastSession (FPCSharpUnity.core.log.ILog) [0x0006f] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameInitController.transformed.cs:285
  at Game.code.control.GameControllerBasic.shutdownSimulation (string) [0x00132] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameControllerBasic.transformed.cs:218
  at Game.code.control.GameController/Init.dispose (bool) [0x0006d] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameController.Init.transformed.cs:882
  at Game.code.control.GameController/Init.Dispose () [0x00001] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameController.Init.transformed.cs:872
  at Game.code.control.GameController.OnDestroy () [0x00000] in W:\work\unity\sb-win\quantum_unity\generated-by-compiler\game\macros\Assets\Game\code\control\GameController.transformed.cs:129
  at (wrapper runtime-invoke) object.runtime_invoke_void__this__ (object,intptr,intptr,intptr) [0x00020] in <695d1cc93cca45069c528c15c9fdd749>:0

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================

Received signal SIGSEGV
Stack trace:
0x00000252c756d7d6 (Mono JIT Code) (wrapper managed-to-native) VivoxCoreInstancePINVOKE:vx_req_sessiongroup_remove_session_t_session_handle_set (System.Runtime.InteropServices.HandleRef,string)
0x00000252c756d64b (Mono JIT Code) [vx_req_sessiongroup_remove_session_t.cs:63] vx_req_sessiongroup_remove_session_t:set_session_handle (string)
0x00000252c756c9bb (Mono JIT Code) [ChannelSession.cs:422] VivoxUnity.Private.ChannelSession:smile:isconnect (System.AsyncCallback)
0x00000252c756c4f4 (Mono JIT Code) [VivoxAPI.Channel.transformed.cs:148] Game.code.control.vivox.VivoxAPI/Channel/<>c__DisplayClass10_0:<leave>b__0 (System.AsyncCallback)
0x00000250dff59cf9 (Mono JIT Code) [VivoxAPI.transformed.cs:163] Game.code.control.vivox.VivoxAPI:callbackToFuture (System.Action`1<System.AsyncCallback>,System.Action`1<System.IAsyncResult>)
0x00000252c756bfa3 (Mono JIT Code) [VivoxAPI.Channel.transformed.cs:148] Game.code.control.vivox.VivoxAPI/Channel:leave (bool)
0x00000252c756aa63 (Mono JIT Code) [GameController.Init.transformed.cs:807] Game.code.control.GameController/Init/<>c__DisplayClass135_15:<.ctor>g__leaveCurrentVivoxChannel|116 ()
0x00000250d662751a (Mono JIT Code) [Subscription.cs:48] FPCSharpUnity.core.reactive.Subscription:unsubscribe ()
0x00000250e228d063 (Mono JIT Code) [Subscription.cs:58] FPCSharpUnity.core.reactive.Subscription:smile:ispose ()
0x00000250c37d4d4c (Mono JIT Code) [DisposableTracker.cs:120] FPCSharpUnity.core.dispose.DisposableTracker:smile:ispose ()
0x00000252c756554e (Mono JIT Code) [GameController.Init.transformed.cs:885] Game.code.control.GameController/Init:dispose (bool)
0x00000252c7564f4b (Mono JIT Code) [GameController.Init.transformed.cs:872] Game.code.control.GameController/Init:smile:ispose ()
0x00000251ab0981f9 (Mono JIT Code) [GameInitController.transformed.cs:285] Game.code.control.GameInitController:disposeLastSession (FPCSharpUnity.core.log.ILog)
0x00000252c75669d3 (Mono JIT Code) [GameControllerBasic.transformed.cs:218] Game.code.control.GameControllerBasic:shutdownSimulation (string)
0x00000252c756546b (Mono JIT Code) [GameController.Init.transformed.cs:882] Game.code.control.GameController/Init:dispose (bool)
0x00000252c7564f4b (Mono JIT Code) [GameController.Init.transformed.cs:872] Game.code.control.GameController/Init:smile:ispose ()
0x00000252c7564e73 (Mono JIT Code) [GameController.transformed.cs:129] Game.code.control.GameController:OnDestroy ()
0x00000250c32bdba8 (Mono JIT Code) (wrapper runtime-invoke) object:runtime_invoke_void__this__ (object,intptr,intptr,intptr)
0x00007ffdbdb4f1e0 (mono-2.0-bdwgc) [mini-runtime.c:2849] mono_jit_runtime_invoke
0x00007ffdbdad2ac2 (mono-2.0-bdwgc) [object.c:2921] do_runtime_invoke
0x00007ffdbdadbb1f (mono-2.0-bdwgc) [object.c:2968] mono_runtime_invoke
0x00007ff75753cf74 (Unity) scripting_method_invoke
0x00007ff757538251 (Unity) ScriptingInvocation::Invoke
0x00007ff7575383ae (Unity) ScriptingInvocation::InvokeChecked
0x00007ff757592b86 (Unity) SerializableManagedRef::CallMethod
0x00007ff757515ad6 (Unity) MonoBehaviour::WillDestroyComponent
0x00007ff756f6c421 (Unity) GameObject::WillDestroyGameObject
0x00007ff7572498c1 (Unity) PreDestroyRecursive
0x00007ff7572475af (Unity) DestroyObjectHighLevel_Internal
0x00007ff7572471c4 (Unity) DestroyObjectHighLevel
0x00007ff757251d4e (Unity) DestroyWorldObjects
0x00007ff7581e99c8 (Unity) EditorSceneManager::RestoreSceneBackups
0x00007ff757f0c6ed (Unity) PlayerLoopController::ExitPlayMode
0x00007ff757f1b7c7 (Unity) PlayerLoopController::SetIsPlaying
0x00007ff757f1e627 (Unity) Application::TickTimer
0x00007ff758363d61 (Unity) MainMessageLoop
0x00007ff758367db1 (Unity) WinMain
0x00007ff7599f75e2 (Unity) __scrt_common_main_seh
0x00007ffe61067034 (KERNEL32) BaseThreadInitThunk
0x00007ffe63042651 (ntdll) RtlUserThreadStart

Code for the workaround:

PlayStateUtils.cs

using ExhaustiveMatching;
using FPCSharpUnity.core.reactive;

namespace FPCSharpUnity.unity.Utilities;

#if UNITY_EDITOR
[UnityEditor.InitializeOnLoad]
#endif
public static class PlayStateUtils {
  /// <summary>
  /// Becomes `false` when we exit the play mode and also when we're about to exit play mode.
  /// <para/>
  /// Works in Editor (by using <see cref="UnityEditor.EditorApplication.playModeStateChanged"/>) and Player (in player
  /// this always returns true).
  /// </summary>
  public static readonly IRxVal<bool> isPlayingAndNotExitingPlayMode;
 
  static PlayStateUtils() {
    isPlayingAndNotExitingPlayMode =
#if UNITY_EDITOR
      createIsPlayingAndNotExitingPlayModeForEditor();
#else
      // If we're not in editor, then we're just always playing.
      RxVal.cached(true)
#endif
   
#if UNITY_EDITOR
    static IRxVal<bool> createIsPlayingAndNotExitingPlayModeForEditor() {
      var rx = RxRef.a(UnityEditor.EditorApplication.isPlaying);
      UnityEditor.EditorApplication.playModeStateChanged += change => rx.value = change switch {
        UnityEditor.PlayModeStateChange.EnteredEditMode => false,
        UnityEditor.PlayModeStateChange.ExitingEditMode => false,
        UnityEditor.PlayModeStateChange.EnteredPlayMode => true,
        UnityEditor.PlayModeStateChange.ExitingPlayMode => false,
        _ => throw ExhaustiveMatch.Failed(change)
      };
      return rx;
    }
#endif
    ;
  }
}

Leave method:

    /// <summary>
    /// Leaves the Vivox channel and (optionally) deletes the channel from the channel list. 
    /// </summary>
    public Future<Try<Unit>> leave(bool deleteFromChannelList = true) {
      var isPlayingAndNotExitingPlayMode = PlayStateUtils.isPlayingAndNotExitingPlayMode.value;
     
      log.mDebug(
        $"{Macros.classAndMethodNameShort}({deleteFromChannelList.echo()}): "
        + $"channel state = {backing.ChannelState}, audio state = {backing.AudioState}, "
        + $"text state = {backing.TextState}, Vivox session state = {api.session.State}, "
        + $"{isPlayingAndNotExitingPlayMode.echo()}"
      );
     
      // Vivox has a bug where it segfaults the whole Unity editor if you try to leave the channel when play mode is
      // being exited in the editor.
      //
      // This is a workaround for that :)
      //
      // https://discussions.unity.com/t/877659
      if (isPlayingAndNotExitingPlayMode) {
        return callbackToFuture(cb => backing.Disconnect(cb), _ => {
          // Delete the channel entry from the channel list after we successfully leave.
          if (deleteFromChannelList) api.session.DeleteChannelSession(id);
        });
      }
      else {
        log.mDebug(
          "Not really leaving Vivox channel to work around a Vivox bug that happens in Unity editor when currently "
          + "exiting play mode."
        );
        return Future.successful(Try.value(Unit._));
      }
    }

Any news? We have a lot of crashes on android platfrom, guys

@dylan_unity3d , why are you ignoring us? We have lots of crashes on android platform at the same conditions. Even crashlog almost the same in core as in the edtior. And as you know, crashes and anrs are the wrost google thing that can be…

Hello! We are sorry for the delay in our response! We receive a lot of requests and questions, so we cannot respond to every question right away, but we are working to provide assistance as quickly as we can!

I am also sorry to hear you are seeing these issues on android. I just have a few follow up questions to help me best analyze your issue.

  • To confirm are you now seeing these crashes in build and not just editor?
  • Were you seeing these crashes before you implemented your workaround?
  • Are you seeing this on every android device you test on?
  • What android devices have you tested this on? (Pixel 4, Samsung 7, etc)
  • Are you still seeing this issue in editor? I know you stated you found a workaround above, is that fixing your issue in editor?

Thank you for your time and we apologize again for the delay.

Hello @Neozman I noticed you made a separate thread for this issue, I’ll post my questions over there: Android crash

  • To confirm are you now seeing these crashes in build and not just editor?

Yes, i’ve seen this crashes on different android devices also. Almost all devices. The reason alwas the same: disconnecting channel on app quiting.

Also in stacktrace we ve seen the same point as in editor:

VivoxCoreInstancePINVOKE.vx_req_sessiongroup_remove_session_t_session_handle_set (System.Runtime.InteropServices.HandleRef,string) [0x0001b] in :0

  • Were you seeing these crashes before you implemented your workaround?

Only on new version. We have been using 5.14 previously and there were no such crashes

  • Are you seeing this on every android device you test on?

Almost

  • What android devices have you tested this on? (Pixel 4, Samsung 7, etc)

Samsung s8, Samsing s20, Redmi Note 6 Pro, etc

  • Are you still seeing this issue in editor? I know you stated you found a workaround above, is that fixing your issue in editor?

After i’ve implemeted my “fix” by setting exit flag before exit, it has gone. But after release i’ve got another crashes that i’ve described in another topic.