lsalzman / enet

ENet reliable UDP networking library
MIT License
2.78k stars 675 forks source link

After creating an ENetPacket to send, when is it considered safe to release the memory of this packet? #229

Closed Steamgjk closed 1 year ago

Steamgjk commented 1 year ago

Assume I am calling enet_packet_create to send an ENetPacket, after I call this API, I am not aware when the packet is sent.

Maybe it is pending somewhere in the data path, so it is risky to immediately release the packet after the API call. My question is: when is it safe to call enet_packet_destroy to release the memory?

lsalzman commented 1 year ago

After you call enet_peer_send, enet owns the packet and will clean it up when its been sent.

Steamgjk commented 1 year ago

After you call enet_peer_send, enet owns the packet and will clean it up when its been sent.

Thanks @lsalzman This is a very important point: Does that mean, if I create an ENetPacket, then I call enet_peer_send Twice, sending the packet to different peers, then it is risky because that may cause double free?

lsalzman commented 1 year ago

No, there is a reference count, which will increase with calls to enet_peer_send. Nothing actually happens that can free the packet until a call to enet_host_service.

Steamgjk commented 1 year ago

No, there is a reference count, which will increase with calls to enet_peer_send. Nothing actually happens that can free the packet until a call to enet_host_service.

Well, how about this sequence:
(1) Create a packet (2) Send the packet to peer-1 by calling enet_peer_send (3) Call enet_host_service (4) Send the packet again to peer-2 by calling enet_peer_send (5) Call enet_host_service

In this case, I think after (3) the packet should have been released, so Step (4) will already cause problems because the data region has become undefined. Is it right?

lsalzman commented 1 year ago

The simple answer to your problem is: don't do that. If you don't understand the internals of the library and can't read the code to find out how it works, it's going to be an unsafe path for you to take. The relevant code in peer.c and packet.c is only a few hundred lines.

The long answer: In that case you need to increase the referenceCount on your own, and when you are ready to get rid of the packet, decrease the reference count. If its zero, then destroy it, it not, then enet owns it, so don't destroy it.