mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Fix autosave timer self-unregister crash risk
The periodic autosave timer called reset_timer() at the end of its
own callback, which unregistered the timer that was still executing
(itself). Blender frees the timer's internal registry entry on that
manual unregister, then frees it again when the callback returns
None - a double free that corrupts the heap and can crash Blender
later, once the corrupted memory is reused.
Reschedule by returning the next interval from the callback instead,
which is the safe, documented way to repeat a bpy.app.timers
callback. External reset_timer() calls (from SaveProject,
LoadProject, AutosavePrompt) are unaffected since they run from a
separate call stack (UI events), not from inside the timer.
Found while investigating a segfault reported when cancelling the
autosave recovery popup; not itself the cause of that crash (see the
following commit), but the same reentrant-unregister pattern and a
real, independent latent bug in the periodic reminder path.
Generated with the assistance of an AI coding tool.
(cherry picked from commit 6306ce0f80)
This commit is contained in:
committed by
Dion Moult
parent
316dace11a
commit
f24e637dc9
@@ -96,9 +96,16 @@ class Autosave:
|
||||
if not cls.is_eligible():
|
||||
return
|
||||
|
||||
def on_timer() -> None:
|
||||
def on_timer() -> Union[float, None]:
|
||||
cls._on_timer_expired()
|
||||
return None
|
||||
# Reschedule by returning the next interval rather than calling
|
||||
# reset_timer(), which would unregister this timer from within
|
||||
# its own callback. Blender frees the timer's internal registry
|
||||
# entry on that manual unregister, then frees it again when the
|
||||
# callback returns - a double free that corrupts the heap and
|
||||
# crashes Blender shortly after (e.g. when the prompt dialog
|
||||
# spawned below is next interacted with).
|
||||
return cls.get_interval_seconds() if cls.is_eligible() else None
|
||||
|
||||
global _timer_callback
|
||||
_timer_callback = on_timer
|
||||
@@ -120,7 +127,6 @@ class Autosave:
|
||||
cls.perform_backup(bpy.context)
|
||||
except Exception as error:
|
||||
print(f"Bonsai: autosave backup failed: {error}")
|
||||
cls.reset_timer()
|
||||
|
||||
@classmethod
|
||||
def perform_backup(cls, context: bpy.types.Context) -> None:
|
||||
|
||||
Reference in New Issue
Block a user