ClientMessage sent during PlayerController Unpossess can crash

We’re getting a crash in ClientMessage (castChecked failing - but since that’s just a static_cast in release it could dereference a bad pointer there) when shutting down the connection on a listen server. I can fix our local issue but I want to find out what the intended behavior is.

The crash is caused by the following:

  • UEngine::ShutdownWorldNetDriver is called, which sets the WorldNetDriver to NULL then calls DestroyNamedNetDriver
  • That goes and, in UNetDriver::Shutdown() destroys all the client connections which destroys all the Pawns.
  • Destroying the pawns calls APawn::DetachFromControllerPendingDestroy which triggers an UnPossess on the controller.
  • We have code that wants to send a ClientMessage on UnPossess. Because we’re no longer on a server (querying World net driver returns NULL), we call the message as local, even on the remote controllers, which have an IpConnection, not a LocalPlayer. Then in APlayerController::ClientTeamMessage_Implementation we fail to cast the IpConnection to a LocalPlayer and we crash.

We can fix the code in our ::UnPossess to not send a ClientMessage in this case(where we’re being torn down), but is it intended that we protect against it there or should we feel safe calling ClientMessage and having the underlying code handle it?