Skip to content

fix: eager listener cleanup via onXxxDeleted callbacks#420

Open
mfazekas wants to merge 2 commits intorive-app:mainfrom
mfazekas:fix/commandqueue-eager-listener-cleanup
Open

fix: eager listener cleanup via onXxxDeleted callbacks#420
mfazekas wants to merge 2 commits intorive-app:mainfrom
mfazekas:fix/commandqueue-eager-listener-cleanup

Conversation

@mfazekas
Copy link
Contributor

Summary

  • Builds on top of fix: use-after-free in CommandQueue delete methods #419. Instead of deferring all listener cleanup to dealloc, listeners are now eagerly cleaned up via onXxxDeleted callbacks when the C++ server confirms deletion
  • Prevents listener accumulation when resources are repeatedly created/destroyed while the Worker stays alive (e.g. loading 100s of files)
  • dealloc remains as safety net for bulk teardown when everything is released at once

mfazekas and others added 2 commits February 9, 2026 13:54
Remove premature listener deletion from all 6 delete methods (deleteFile, deleteArtboard, deleteViewModelInstance, deleteImage, deleteFont, deleteAudio). The C++ CommandQueue still holds raw pointers to listeners after deletion, causing EXC_BAD_ACCESS when processMessages() invokes callbacks through dangling pointers. Listeners are already cleaned up in dealloc.
Instead of deferring all listener cleanup to CommandQueue dealloc,
clean up listeners as soon as the C++ server confirms deletion via
onXxxDeleted callbacks. This prevents listener accumulation when
resources are created and destroyed while the Worker stays alive.

Dealloc remains as a safety net for bulk teardown (when the Worker
itself is released alongside all resources).

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@dskuza
Copy link
Collaborator

dskuza commented Feb 10, 2026

I like the idea, but I'm a little hesitant on reusing the c++ listeners to delegate back to the command queue. I'd like to keep that as just a listener that forwards to an observer / delegate to bridge to ObjC, if possible. Granted, it is one way to do it. The other way I was thinking is that if you look at File.swift, for example, we defer to the file service on deinit to delete the file handle. Right now, that is just a synchronous request. FileService could add a cleanup function that then forwards to the command queue once a file is deleted, either in its callback, or in some place like File's deinit function that uses the service to delete the file. That would require turning the file deletion function async, and adding a second function call, which I'm not totally against, simply for separation of concern.

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.

2 participants