In IL2CPP Debug builds, starting a Replication Server through Launcher.Create kills the player with a Visual C++ assertion dialog

(Please make the title of your topic brief but informative, and post error messages under the next heading Details and error message(s))

Description, details and error message(s)

A Windows IL2CPP player aborts the moment it starts a self-hosted Replication Server through
Launcher.Create. The process dies with a C runtime dialog. There is no managed exception, no Unity crash dump, and no Windows Error Reporting record — the Player.log simply stops mid-line.

Microsoft Visual C++ Runtime Library
Debug Assertion Failed!
Program: ...\GameAssembly.dll
File: <UnityEditor>\Data\il2cpp\libil2cpp\icalls\System\System.Diagnostics\Process.cpp
Line: 40
Expression: 0 && "Process::GetProcesses_internal"

The cause is in Launcher.Create (Coherence.Toolkit/ReplicationServer/Launcher.cs):

var process = new NlProcess(startupInfo);
if (process.IsProcessAlreadyRunning())
{
    throw new System.Exception("RS is already running.");
}

NlProcess.IsProcessAlreadyRunning() (Coherence.Plugins/NativeLauncher/NlProcess.cs) calls System.Diagnostics.Process.GetProcessesByName(...), which reaches theProcess::GetProcesses_internalicall. IL2CPP does not implement it:

Il2CppArray* Process::GetProcesses_internal()
{
    IL2CPP_NOT_IMPLEMENTED_ICALL(Process::GetProcesses_internal);
    return 0;
}

IL2CPP_NOT_IMPLEMENTED_ICALL expands to IL2CPP_ASSERT(0 && ...), which is a native abort wheneverIL2CPP_DEBUG is defined. IL2CPP_DEBUG is defined when the player is built with
Il2CppCompilerConfiguration.Debug, a normal choice for development builds because it cuts C++ compile time substantially. The try/catch inside IsProcessAlreadyRunning cannot catch a native abort.

There is a second-order problem. With Il2CppCompilerConfiguration.Release the assert compiles tovoid(0) and the icall returns null. The BCL then dereferences a null array and the outercatch (Exception) in IsProcessAlreadyRunning returns false. So the duplicate-server guard never
functions in any IL2CPP player: it either aborts the process or silently answers “not running”,
whatever is actually running.

Worth noting that the native launcher (native_utils.dll) was added in 1.4.0 specifically so IL2CPP players could launch a Replication Server, because Process.Start is equally unimplemented under IL2CPP (Process::CreateProcess_internal, same source file). IsProcessAlreadyRunning reintroduces a System.Diagnostics.Process dependency on that same path.

Expected behaviour

Launcher.Create should return a usable IReplicationServer in an IL2CPP player, as it does under Mono and in the Editor. The duplicate-server check should either work under IL2CPP or be skipped there, rather than aborting the process.

Screenshots

How to reproduce

Rate:
Every time

Steps:

  1. Build a Windows Standalone player with Scripting Backend = IL2CPP and
    Il2CppCompilerConfiguration.Debug (Player Settings > C++ Compiler Configuration = Debug).

  2. In that player, call:

  3. var config = new ReplicationServerConfig
    {
        Mode = Mode.World,
        APIPort = (ushort)RuntimeSettings.Instance.WorldsAPIPort,
        UDPPort = (ushort)RuntimeSettings.Instance.LocalWorldUDPPort,
        SignallingPort = (ushort)(RuntimeSettings.Instance.LocalWorldUDPPort + 1),
        SendFrequency = 20,
        ReceiveFrequency = 60,
        AutoShutdownTimeout = 60000,
    };
    
    var server = Launcher.Create(config);   // aborts here
    server.Start();
    
  4. The player aborts inside Launcher.Create, before Start is reached. Setting C++ Compiler Configuration to Release removes the abort, but then the check silently always
    returns false, as described above.

    The shipped replication-server.exe itself is fine. Running it by hand with the exact arguments the Launcher generates starts and binds all ports normally.

Environment

  • coherence SDK: 2.2.0
  • Unity: 6000.5.7f1
  • OS / Platform: Windows 11, Standalone Windows x64, IL2CPP, Development Build
  • Replication Server: v8.1.3

Suggested fix

Answer the “already running” question through the native launcher rather than
System.Diagnostics.Process, or skip the check under ENABLE_IL2CPP so Create cannot abort.