Skip to content

Commit 66d4134

Browse files
fix: Fix for NullReferenceException during client Shutdown (#2921)
* Fixed crash and added test for a message still existing in the message queue on shutdown. * Fixing format errors. --------- Co-authored-by: Noel Stephens <[email protected]>
1 parent f9c6731 commit 66d4134

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

com.unity.netcode.gameobjects/Runtime/Core/NetworkManager.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,6 @@ internal void ShutdownInternal()
11881188

11891189
// Everything is shutdown in the order of their dependencies
11901190
DeferredMessageManager?.CleanupAllTriggers();
1191-
CustomMessagingManager = null;
11921191

11931192
RpcTarget?.Dispose();
11941193
RpcTarget = null;
@@ -1199,6 +1198,8 @@ internal void ShutdownInternal()
11991198
// Shutdown connection manager last which shuts down transport
12001199
ConnectionManager.Shutdown();
12011200

1201+
CustomMessagingManager = null;
1202+
12021203
if (MessageManager != null)
12031204
{
12041205
MessageManager.Dispose();

com.unity.netcode.gameobjects/Tests/Runtime/NetworkManagerCustomMessageManagerTests.cs

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
using System.Collections;
12
using NUnit.Framework;
3+
using Unity.Collections;
4+
using Unity.Netcode.TestHelpers.Runtime;
25
using UnityEngine;
6+
using UnityEngine.TestTools;
37

48
namespace Unity.Netcode.RuntimeTests
59
{
@@ -30,5 +34,87 @@ public void CustomMessageManagerAssigned()
3034
networkManager.Shutdown();
3135
Object.DestroyImmediate(gameObject);
3236
}
37+
38+
[UnityTest]
39+
public IEnumerator VerifyCustomMessageShutdownOrder()
40+
{
41+
Assert.True(NetcodeIntegrationTestHelpers.Create(1, out NetworkManager server, out NetworkManager[] clients));
42+
43+
bool isHost = false;
44+
45+
// Start server to cause initialization
46+
NetcodeIntegrationTestHelpers.Start(isHost, server, clients);
47+
48+
// [Client-Side] Wait for a connection to the server
49+
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnected(clients, null, 512);
50+
51+
// [Host-Side] Check to make sure all clients are connected
52+
yield return NetcodeIntegrationTestHelpers.WaitForClientsConnectedToServer(server, isHost ? (clients.Length + 1) : clients.Length, null, 512);
53+
54+
// Create a message to pass directly to the message handler. If we send the message its processed before we get a chance to shutdown
55+
56+
var dummySendData = new FastBufferWriter(128, Allocator.Temp);
57+
dummySendData.WriteValueSafe("Dummy Data");
58+
59+
// make the message
60+
var unnamedMessage = new UnnamedMessage
61+
{
62+
SendData = dummySendData
63+
};
64+
65+
// make the message
66+
using var serializedMessage = new FastBufferWriter(128, Allocator.Temp);
67+
unnamedMessage.Serialize(serializedMessage, 0);
68+
69+
// Generate the full message
70+
var messageHeader = new NetworkMessageHeader
71+
{
72+
MessageSize = (uint)serializedMessage.Length,
73+
MessageType = server.MessageManager.GetMessageType(typeof(UnnamedMessage)),
74+
};
75+
76+
var fullMessage = new FastBufferWriter(512, Allocator.Temp);
77+
BytePacker.WriteValueBitPacked(fullMessage, messageHeader.MessageType);
78+
BytePacker.WriteValueBitPacked(fullMessage, messageHeader.MessageSize);
79+
80+
fullMessage.WriteBytesSafe(serializedMessage.ToArray());
81+
82+
// Pack the message into a batch
83+
var batchHeader = new NetworkBatchHeader
84+
{
85+
BatchCount = 1
86+
};
87+
88+
var batchedMessage = new FastBufferWriter(1100, Allocator.Temp);
89+
using (batchedMessage)
90+
{
91+
batchedMessage.TryBeginWrite(FastBufferWriter.GetWriteSize(batchHeader) +
92+
FastBufferWriter.GetWriteSize(fullMessage));
93+
batchedMessage.WriteValue(batchHeader);
94+
batchedMessage.WriteBytesSafe(fullMessage.ToArray());
95+
96+
// Fill out the rest of the batch header
97+
batchedMessage.Seek(0);
98+
batchHeader = new NetworkBatchHeader
99+
{
100+
Magic = NetworkBatchHeader.MagicValue,
101+
BatchSize = batchedMessage.Length,
102+
BatchHash = XXHash.Hash64(fullMessage.ToArray()),
103+
BatchCount = 1
104+
};
105+
batchedMessage.WriteValue(batchHeader);
106+
107+
// Handle the message as if it came from the server/client
108+
server.MessageManager.HandleIncomingData(clients[0].LocalClientId, batchedMessage.ToArray(), 0);
109+
110+
foreach (var c in clients)
111+
{
112+
c.MessageManager.HandleIncomingData(server.LocalClientId, batchedMessage.ToArray(), 0);
113+
}
114+
}
115+
116+
// shutdown the network managher
117+
NetcodeIntegrationTestHelpers.Destroy();
118+
}
33119
}
34120
}

0 commit comments

Comments
 (0)