(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:
-
Build a Windows Standalone player with Scripting Backend = IL2CPP and
Il2CppCompilerConfiguration.Debug(Player Settings > C++ Compiler Configuration = Debug). -
In that player, call:
-
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(); -
The player aborts inside
Launcher.Create, beforeStartis 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.exeitself 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.



