I'm using boost::asio for UDP communication and I'm experiencing what appears to be random crashes, which I don't even know how to begin to solve. I've been trying to figure this out for 3 weeks now and I'm about at my wit's end.
Some information I've discovered while working on this:
- It only happens about every 1 in 3 times I run it.
- When I add console output using std::cout that is written once every frame, it never happens. I have no idea why this would affect it.
- It only happens when I run the exe directly. When I run it in visual studio in either debug or release mode, it's fine.
- It only happens when I'm running the client and the server within the same process. If I run one machine as a dedicated server and another as a client it does not happen.
- It only seems to be a problem when it's in my actual game engine. I created a bare bones process that does nothing but simulates the UDP communication that the game would do, and that works fine.
- I've tried having the client and server IO done in two separate threads with two separate io_service objects, as well as in the same thread with a single io_service. There was no difference either way.
The crash happens during the initiation/synchronization step.The protocol is as follows:
- The client sends a connection initiation packet to the server.
- Upon receiving this, the server sends to the client a few packets containing a list of UUID and integer ID pairs.
- The client receives each of these packets, and builds its own map of the server generated IDs to the client generated IDs.
Here's a screenshot of the console output, which shows that it is crashing in the middle of writing a line in the client's handleReceive function. I should not, it doesn't always crash at this very moment. Sometimes it does write out all console lines fully.
Here is the code of the handleReceive function in the client IO thread:
void UdpClient::handleReceive(const boost::system::error_code& error, std::size_t bytesReceived)
{
if ((!error || error == error::message_size) && bytesReceived > 0 && udpPacket_.decodeHeader())
{
UdpPacketType packetType = udpPacket_.getPacketType();
int bodyLength = udpPacket_.getBodyLength();
char* body = udpPacket_.getBody();
switch (packetType)
{
case UDP_PACKET_SERVER_ID_LIST: // Read a batch of IDs from the server, and map them to client IDs.
{
DebugHelper::streamLock->lock();
std::cout << "[" << boost::this_thread::get_id() << "] Synching IDs on client. "<<std::endl;
DebugHelper::streamLock->unlock();
int uuidSize = boost::uuids::uuid::static_size();
// Combined size of a UUID and an integer ID.
int combinedSize = sizeof(int) + uuidSize;
for (int i = 0; i < bodyLength; i += combinedSize)
{
// Read the UUID from the packet body.
boost::uuids::uuid uuid = networkUtility_.buildUuid(body, i);
// Read the server generated integer ID from the packet body.
int serverId = networkUtility_.buildInteger(body, i + uuidSize);
// Get the locally generated integer ID.
int localId = BaseIds::getIntegerFromUuid(uuid);
clientLayer_->mapLocalIdToServerId(localId, serverId);
}
DebugHelper::streamLock->lock();
std::cout << "[" << boost::this_thread::get_id() << "] ID batch processed on client. "<<std::endl;
DebugHelper::streamLock->unlock();
break;
}
I don't know if maybe there are some tricks to working with threads, or UDP/IP that might be helpful? I'm just completely stuck at this point and I don't know where to go from here. Any ideas are appreciated!