Skip to content

Commit 86c6255

Browse files
authored
Fix race condition in FlutterSurfaceManager (flutter#27828)
1 parent 49f4eaa commit 86c6255

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

shell/platform/darwin/macos/framework/Source/FlutterSurfaceManager.mm

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ @implementation FlutterIOSurfaceManager {
2727

2828
CGSize _surfaceSize;
2929
FlutterIOSurfaceHolder* _ioSurfaces[kFlutterSurfaceManagerBufferCount];
30+
BOOL _frameInProgress;
3031
}
3132

3233
- (instancetype)initWithLayer:(CALayer*)containingLayer contentTransform:(CATransform3D)transform {
@@ -66,23 +67,33 @@ - (void)swapBuffers {
6667
_ioSurfaces[kFlutterSurfaceManagerFrontBuffer]);
6768
[_delegate onSwapBuffers];
6869

69-
dispatch_async(dispatch_get_main_queue(), ^{
70-
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onIdle) object:nil];
71-
[self performSelector:@selector(onIdle) withObject:nil afterDelay:kIdleDelay];
72-
});
70+
// performSelector:withObject:afterDelay needs to be performed on RunLoop thread
71+
[self performSelectorOnMainThread:@selector(reschedule) withObject:nil waitUntilDone:NO];
72+
73+
@synchronized(self) {
74+
_frameInProgress = NO;
75+
}
76+
}
77+
78+
- (void)reschedule {
79+
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onIdle) object:nil];
80+
[self performSelector:@selector(onIdle) withObject:nil afterDelay:kIdleDelay];
7381
}
7482

7583
- (void)onIdle {
7684
@synchronized(self) {
77-
// Release the back buffer and notify delegate. The buffer will be restored
78-
// on demand in ensureBackBuffer
79-
_ioSurfaces[kFlutterSurfaceManagerBackBuffer] = nil;
80-
[self.delegate onSurfaceReleased:kFlutterSurfaceManagerBackBuffer];
85+
if (!_frameInProgress) {
86+
// Release the back buffer and notify delegate. The buffer will be restored
87+
// on demand in ensureBackBuffer
88+
_ioSurfaces[kFlutterSurfaceManagerBackBuffer] = nil;
89+
[self.delegate onSurfaceReleased:kFlutterSurfaceManagerBackBuffer];
90+
}
8191
}
8292
}
8393

8494
- (void)ensureBackBuffer {
8595
@synchronized(self) {
96+
_frameInProgress = YES;
8697
if (_ioSurfaces[kFlutterSurfaceManagerBackBuffer] == nil) {
8798
// Restore previously released backbuffer
8899
_ioSurfaces[kFlutterSurfaceManagerBackBuffer] = [[FlutterIOSurfaceHolder alloc] init];

0 commit comments

Comments
 (0)