Skip to content

Fix crash from engineFreeModel racing destroyElement deferred deletion#4970

Merged
Lpsd merged 1 commit into
multitheftauto:masterfrom
TheCrazy17:fix/freemodel-deferred-destroy-crash
Jun 21, 2026
Merged

Fix crash from engineFreeModel racing destroyElement deferred deletion#4970
Lpsd merged 1 commit into
multitheftauto:masterfrom
TheCrazy17:fix/freemodel-deferred-destroy-crash

Conversation

@TheCrazy17

Copy link
Copy Markdown
Contributor

Summary

engineFreeModel now flushes the deferred element-deletion queue before freeing a models collision/DFF data.

Motivation

Calling engineFreeModel right after destroyElement on an entity using that model crashes the game. destroyElement only flags the element and defers the actual native entity deletion to the next pulse (see CElementDeleter). If a script frees the model in the same tick, the native entity is still alive in the game world, and another entity's collision processing (CEntity::GetIsTouching/GetBoundRadius, called from CPhysical::ProcessCollisionSectorList) can still find it and read its now-freed CColModel, crashing with an access violation.

Closes #3316

Test plan

  • Reproduced the crash using engineFreeModel called immediately after destroyElement on a vehicle using a custom-content model.
  • Applied the fix and confirmed the same sequence no longer crashes.

Checklist

  • Your code should follow the coding guidelines.
  • Smaller pull requests are easier to review. If your pull request is beefy, your pull request should be reviewable commit-by-commit.

destroyElement() defers the native entity's actual removal to the
next pulse. If a script frees a model in the same tick it destroyed
an entity using it, that entity is still alive in the game world and
other entities' collision processing can still find it the moment
its collision data is freed, crashing the client. Flush the deferred
deletion queue first so any such entity is fully gone before the
model is freed.
@Lpsd Lpsd merged commit 3ab54e4 into multitheftauto:master Jun 21, 2026
10 checks passed
Lpsd pushed a commit to Lpsd/mtasa-blue that referenced this pull request Jun 22, 2026
multitheftauto#4970)

### Summary

`engineFreeModel` now flushes the deferred element-deletion queue before
freeing a models collision/DFF data.

### Motivation

Calling `engineFreeModel` right after `destroyElement` on an entity
using that model crashes the game. `destroyElement` only flags the
element and defers the actual native entity deletion to the next pulse
(see `CElementDeleter`). If a script frees the model in the same tick,
the native entity is still alive in the game world, and another entity's
collision processing (`CEntity::GetIsTouching`/`GetBoundRadius`, called
from `CPhysical::ProcessCollisionSectorList`) can still find it and read
its now-freed `CColModel`, crashing with an access violation.


Closes multitheftauto#3316

### Test plan

- Reproduced the crash using `engineFreeModel` called immediately after
`destroyElement` on a vehicle using a custom-content model.
- Applied the fix and confirmed the same sequence no longer crashes.

### Checklist

* [x] Your code should follow the [coding
guidelines](https://wiki.multitheftauto.com/index.php?title=Coding_guidelines).
* [x] Smaller pull requests are easier to review. If your pull request
is beefy, your pull request should be reviewable commit-by-commit.
@TheCrazy17 TheCrazy17 deleted the fix/freemodel-deferred-destroy-crash branch June 23, 2026 01:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Freeing custom id of an element right after it's destroyed is causing crash

2 participants