Fix crash when removing a sync objects and iterating at the same time

This commit is contained in:
MysterD 2023-03-27 20:25:35 -07:00
parent f4fe5a9457
commit 7df87d583e
5 changed files with 22 additions and 15 deletions

View File

@ -11454,6 +11454,9 @@ ANIM_FLAG_NOLOOP = (1 << 0)
--- @type integer
ANIM_FLAG_VERT_TRANS = (1 << 4)
--- @type integer
COOP_OBJ_FLAG_INITIALIZED = (1 << 3)
--- @type integer
COOP_OBJ_FLAG_LUA = (1 << 1)
@ -11519,10 +11522,10 @@ MAX_VERSION_LENGTH = 10
MINOR_VERSION_NUMBER = 0
--- @type integer
PATCH_VERSION_NUMBER = 3
PATCH_VERSION_NUMBER = 0
--- @type integer
VERSION_NUMBER = 32
VERSION_NUMBER = 33
--- @type string
VERSION_TEXT = "beta"

View File

@ -4056,6 +4056,7 @@
- ANIM_FLAG_HOR_TRANS
- ANIM_FLAG_NOLOOP
- ANIM_FLAG_VERT_TRANS
- COOP_OBJ_FLAG_INITIALIZED
- COOP_OBJ_FLAG_LUA
- COOP_OBJ_FLAG_NETWORK
- COOP_OBJ_FLAG_NON_SYNC

View File

@ -4012,10 +4012,11 @@ char gSmluaConstants[] = ""
"COOP_OBJ_FLAG_NETWORK = (1 << 0)\n"
"COOP_OBJ_FLAG_LUA = (1 << 1)\n"
"COOP_OBJ_FLAG_NON_SYNC = (1 << 2)\n"
"COOP_OBJ_FLAG_INITIALIZED = (1 << 3)\n"
"VERSION_TEXT = 'beta'\n"
"VERSION_NUMBER = 32\n"
"VERSION_NUMBER = 33\n"
"MINOR_VERSION_NUMBER = 0\n"
"PATCH_VERSION_NUMBER = 3\n"
"PATCH_VERSION_NUMBER = 0\n"
"MAX_VERSION_LENGTH = 10\n"
"MAX_LOCAL_VERSION_LENGTH = 12\n"
;

View File

@ -15,6 +15,8 @@
void* sSoMap = NULL;
void* sSoIter = NULL;
#define FORGET_TIMEOUT 10
struct SyncObjectForgetEntry {
struct SyncObject* so;
s32 forgetTimer;
@ -51,6 +53,9 @@ void sync_objects_update(void) {
struct SyncObjectForgetEntry* entry = sForgetList;
while (entry) {
struct SyncObjectForgetEntry* next = entry->next;
if (entry->forgetTimer == FORGET_TIMEOUT) {
hmap_del(sSoMap, entry->so->id);
}
if (entry->forgetTimer-- <= 0) {
if (prev) {
@ -74,17 +79,16 @@ void sync_objects_clear(void) {
sNextSyncId = SYNC_ID_BLOCK_SIZE / 2;
network_on_init_area();
sFreeingAll = true;
for (struct SyncObject* so = sync_object_get_first(); so != NULL; so = sync_object_get_next()) {
sync_object_forget(so->id);
}
sFreeingAll = false;
hmap_clear(sSoMap);
}
void sync_object_forget(u32 syncId) {
struct SyncObject* so = sync_object_get(syncId);
if (!so) { return; }
if (so->forgetting) { return; }
// invalidate last packet sent
if (so != NULL && so->o != NULL && so->o->oSyncID < SYNC_ID_BLOCK_SIZE) {
@ -103,20 +107,17 @@ void sync_object_forget(u32 syncId) {
gCurrentObject = lastObject;
}
so->o = NULL;
so->behavior = NULL;
so->owned = false;
if (!sFreeingAll) {
hmap_del(sSoMap, syncId);
if (so->o) {
so->o->oSyncID = 0;
}
so->forgetting = true;
// add it to a list to free later
s32 forgetCount = 1;
struct SyncObjectForgetEntry* newEntry = calloc(1, sizeof(struct SyncObjectForgetEntry));
newEntry->so = so;
newEntry->forgetTimer = 10;
newEntry->forgetTimer = FORGET_TIMEOUT;
if (sForgetList == NULL) {
sForgetList = newEntry;
} else {
@ -411,7 +412,7 @@ bool sync_object_set_id(struct Object* o) {
so = calloc(1, sizeof(struct SyncObject));
so->extendedModelId = 0xFFFF;
hmap_put(sSoMap, syncId, so);
LOG_INFO("Allocated sync object @ %u, size %ld", syncId, hmap_len(sSoMap));
LOG_INFO("Allocated sync object @ %u, size %ld", syncId, (long int)hmap_len(sSoMap));
} else if (so->o != o) {
LOG_INFO("Already exists...");
}

View File

@ -35,6 +35,7 @@ struct SyncObject {
bool lastReliablePacketIsStale;
u16 extendedModelId;
struct Packet lastReliablePacket;
u8 forgetting;
};