Skip to content

Commit

Permalink
Fix hard to find crash in MLDelayableTimer
Browse files Browse the repository at this point in the history
This crash seems to be a bug in a compiler optimization, releasing the
MLDelayableTimer object and its ivars (like the _cancelHamdler block)
and then trying to call the _cancelHandler ivar (which is nil at this point).

I had to disassemble the Mach-O binary in our Monal.ipa release file
using llvm-otool and use that disassembly together with the crash report
to reconstruct what was happening.

000000000055057c	mov	x0, x19
0000000000550580	bl	_objc_msgSend$invalidate
0000000000550584	mov	x0, x19
0000000000550588	bl	0x564908 ; symbol stub for: _objc_sync_exit
000000000055058c	mov	x0, x19
0000000000550590	bl	0x56486c ; symbol stub for: _objc_release	; <-- unexpected ARC release of self in [MLDelayableTimer cancel]
0000000000550594	ldr	x0, [x19, #0x10]                                ; <-- load of now zeroed _cancelHandler ivar that should point to an objc block
0000000000550598	ldr	x2, [x0, #0x10]                                 ; <-- crash while trying to access the pointer to the code inside our objc block (we try to access the invalid address 0x0000000000000010)
000000000055059c	mov	x1, x19
00000000005505a0	ldp	x29, x30, [sp, #0x30]
00000000005505a4	ldp	x20, x19, [sp, #0x20]
00000000005505a8	add	sp, sp, #0x40
00000000005505ac	br	x2
  • Loading branch information
tmolitor-stud-tu committed Feb 22, 2025
1 parent 276b2e1 commit 8bf1d29
Showing 1 changed file with 5 additions and 2 deletions.
7 changes: 5 additions & 2 deletions Monal/Classes/MLDelayableTimer.m
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ -(void) pause
return;
}
NSTimeInterval remaining = _wrappedTimer.fireDate.timeIntervalSinceNow;
if(remaining == 0)
if(remaining < 0.001)
{
DDLogWarn(@"Tried to pause timer the exact second its firing: %@", self);
return;
Expand Down Expand Up @@ -121,8 +121,11 @@ -(void) cancel
}
DDLogDebug(@"Canceling timer: %@", self);
[self invalidate];
[self scheduleBlockInRunLoop:^{
if(self->_cancelHandler != nil)
self->_cancelHandler(self);
}];
}
_cancelHandler(self);
}

-(void) invalidate
Expand Down

0 comments on commit 8bf1d29

Please sign in to comment.