-[FBSSceneSnapshotRequestHandle performRequestForScene:]

这个卡死堆栈涉及到 FrontBoardServices 的场景快照请求,是一个典型的 系统级死锁问题。以下是详细分析和解决方案:

堆栈分析

关键组件说明

  • FrontBoardServices (FBS):iOS 的窗口和场景管理服务
  • FBSSceneSnapshotRequest:场景快照请求(用于多任务切换、应用截图等)
  • 信号量等待dispatch_semaphore_wait_slow 表明线程在等待某个资源

死锁发生位置

4 FrontBoardServices -[FBSSceneSnapshotRequestHandle performRequestForScene:] + 636
5 FrontBoardServices -[FBSSceneSnapshotAction snapshotRequest:performWithContext:] + 208
6 FrontBoardServices -[FBSSceneSnapshotRequest performSnapshotWithContext:] + 224

死锁原因分析

1. 主线程阻塞导致快照无法完成

// 可能的阻塞场景
- (void)viewDidLoad {
    [super viewDidLoad];
    
    // ❌ 危险:主线程同步网络请求
    NSData *data = [NSData dataWithContentsOfURL:url];
    
    // ❌ 危险:主线程大量计算
    for (int i = 0; i < 1000000; i++) {
        // 耗时计算
    }
    
    // ❌ 危险:主线程文件操作
    NSString *largeFile = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
}

2. 视图渲染性能问题

// 视图渲染导致的卡顿
- (void)drawRect:(CGRect)rect {
    // ❌ 复杂图形绘制
    for (int i = 0; i < 1000; i++) {
        CGContextDrawPath(context, kCGPathFillStroke);
    }
    
    // ❌ 大量图层操作
    for (UIView *subview in self.subviews) {
        subview.layer.shadowOpacity = 0.5;
        subview.layer.cornerRadius = 10;
    }
}

3. 自定义转场动画冲突

// 自定义转场与系统快照冲突
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    // ❌ 长时间动画阻塞主线程
    [UIView animateWithDuration:5.0 animations:^{
        // 长时间动画
    }];
}

解决方案

方案一:主线程性能优化

// 主线程工作负载优化
@implementation MainThreadOptimizer

// 1. 检测主线程阻塞
- (void)setupMainThreadMonitor {
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        
        switch (activity) {
            case kCFRunLoopBeforeWaiting:
                // 主线程空闲
                self.lastIdleTime = [NSDate date];
                break;
            case kCFRunLoopAfterWaiting:
                // 检查是否阻塞太久
                if (self.lastIdleTime && [[NSDate date] timeIntervalSinceDate:self.lastIdleTime] > 0.5) {
                    NSLog(@"⚠️ 主线程可能阻塞: %.2fs", [[NSDate date] timeIntervalSinceDate:self.lastIdleTime]);
                    [self recoverFromBlocking];
                }
                break;
        }
    });
    
    CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
}

// 2. 异步处理耗时操作
- (void)asyncProcessHeavyWork {
    // ✅ 安全:后台处理数据
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:url];
        
        // 回到主线程更新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            [self updateUIWithData:data];
        });
    });
}

// 3. 视图渲染优化
- (void)optimizeViewRendering {
    // 使用 Instruments 识别性能瓶颈
    [self enableRenderingOptimizations];
}

- (void)enableRenderingOptimizations {
    // 减少图层混合
    self.view.layer.opaque = YES;
    
    // 减少阴影复杂度
    self.view.layer.shadowPath = [UIBezierPath bezierPathWithRect:self.view.bounds].CGPath;
    
    // 使用光栅化缓存静态内容
    self.view.layer.shouldRasterize = YES;
    self.view.layer.rasterizationScale = [UIScreen mainScreen].scale;
}

@end

方案二:快照请求处理优化

// 系统快照请求的预处理
@implementation SnapshotRequestHandler

// 1. 准备快照前的状态
- (void)prepareForSnapshot {
    // 确保主线程空闲
    [self ensureMainThreadReady];
    
    // 暂停非必要动画
    [self pauseNonEssentialAnimations];
    
    // 简化视图层次
    [self simplifyViewHierarchyForSnapshot];
}

// 2. 主线程准备检查
- (void)ensureMainThreadReady {
    // 检查主线程是否忙碌
    if ([self isMainThreadBusy]) {
        NSLog(@"⚠️ 主线程忙碌,延迟快照准备");
        [self performSelector:@selector(ensureMainThreadReady) withObject:nil afterDelay:0.1];
        return;
    }
    
    // 完成准备工作
    [self completePreparation];
}

// 3. 动画管理
- (void)pauseNonEssentialAnimations {
    // 暂停自定义动画
    for (UIView *view in [self findAllAnimatingViews]) {
        [view.layer removeAllAnimations];
    }
    
    // 暂停视频播放
    [self pauseMediaPlayback];
}

// 4. 视图层次简化
- (void)simplifyViewHierarchyForSnapshot {
    // 临时隐藏复杂视图
    for (UIView *complexView in [self findComplexViews]) {
        complexView.hidden = YES;
    }
    
    // 减少透明度
    self.view.alpha = 1.0;
}

// 5. 应用状态通知处理
- (void)setupApplicationStateObservers {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationWillResignActive:)
                                                 name:UIApplicationWillResignActiveNotification
                                               object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(applicationDidEnterBackground:)
                                                 name:UIApplicationDidEnterBackgroundNotification
                                               object:nil];
}

- (void)applicationWillResignActive:(NSNotification *)notification {
    // 应用即将进入后台,准备快照
    [self prepareForSnapshot];
}

- (void)applicationDidEnterBackground:(NSNotification *)notification {
    // 恢复视图状态
    [self restoreViewHierarchy];
}

@end

方案三:自定义快照处理

// 自定义快照生成以避免系统死锁
@interface CustomSnapshotGenerator : NSObject
@property (nonatomic, weak) UIWindow *window;
@end

@implementation CustomSnapshotGenerator

// 1. 主动生成快照
- (UIImage *)generateCustomSnapshot {
    // 在后台线程生成快照
    __block UIImage *snapshot = nil;
    
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        // 确保主线程空闲
        [self waitForMainThreadIdle];
        
        // 在主线程生成快照
        dispatch_async(dispatch_get_main_queue(), ^{
            @try {
                snapshot = [self safeSnapshot];
            } @catch (NSException *exception) {
                NSLog(@"❌ 快照生成失败: %@", exception);
            } @finally {
                dispatch_semaphore_signal(semaphore);
            }
        });
    });
    
    // 等待快照生成完成
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    
    return snapshot;
}

// 2. 安全的快照生成
- (UIImage *)safeSnapshot {
    // 使用替代方案生成快照
    UIGraphicsBeginImageContextWithOptions(self.window.bounds.size, NO, 0);
    
    @try {
        // 方法1: 使用layer渲染
        [self.window.layer renderInContext:UIGraphicsGetCurrentContext()];
        
        // 方法2: 使用drawViewHierarchy (更安全)
        // [self.window drawViewHierarchyInRect:self.window.bounds afterScreenUpdates:NO];
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        return image;
    } @catch (NSException *exception) {
        NSLog(@"❌ 快照异常: %@", exception);
        return nil;
    } @finally {
        UIGraphicsEndImageContext();
    }
}

// 3. 主线程空闲等待
- (void)waitForMainThreadIdle {
    // 等待主线程变为空闲状态
    NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:2.0];
    
    while ([self isMainThreadBusy] && [timeout timeIntervalSinceNow] > 0) {
        [NSThread sleepForTimeInterval:0.01];
    }
    
    if ([timeout timeIntervalSinceNow] <= 0) {
        NSLog(@"⚠️ 主线程持续忙碌,强制生成快照");
    }
}

// 4. 主线程忙碌检测
- (BOOL)isMainThreadBusy {
    // 检查RunLoop状态
    CFRunLoopActivity activity = CFRunLoopGetActivity(CFRunLoopGetMain());
    return activity != kCFRunLoopBeforeWaiting;
}

@end

方案四:死锁检测和恢复

// 死锁检测和自动恢复机制
@interface DeadlockDetector : NSObject
@property (nonatomic, assign) NSTimeInterval lastSnapshotTime;
@property (nonatomic, assign) BOOL snapshotInProgress;
@end

@implementation DeadlockDetector

+ (instancetype)shared {
    static DeadlockDetector *instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[DeadlockDetector alloc] init];
    });
    return instance;
}

// 1. 启动死锁监控
- (void)startDeadlockMonitoring {
    [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(checkForDeadlock) userInfo:nil repeats:YES];
}

// 2. 死锁检测
- (void)checkForDeadlock {
    // 检查快照请求是否卡住
    if (self.snapshotInProgress) {
        NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:self.lastSnapshotTime];
        
        if (duration > 3.0) { // 3秒超时
            NSLog(@"⚠️ 检测到快照死锁,持续时间: %.2fs", duration);
            [self recoverFromSnapshotDeadlock];
        }
    }
}

// 3. 快照开始标记
- (void)snapshotWillStart {
    self.snapshotInProgress = YES;
    self.lastSnapshotTime = [NSDate date];
}

// 4. 快照完成标记
- (void)snapshotDidComplete {
    self.snapshotInProgress = NO;
}

// 5. 死锁恢复
- (void)recoverFromSnapshotDeadlock {
    NSLog(@"🔄 执行快照死锁恢复");
    
    // 强制取消所有快照请求
    [self cancelPendingSnapshots];
    
    // 释放可能阻塞的资源
    [self releaseBlockingResources];
    
    // 重置状态
    self.snapshotInProgress = NO;
    
    // 生成替代快照
    [self generateAlternativeSnapshot];
}

- (void)cancelPendingSnapshots {
    // 尝试中断快照进程
    [[NSNotificationCenter defaultCenter] postNotificationName:@"CancelSnapshotOperations" object:nil];
}

- (void)generateAlternativeSnapshot {
    // 使用自定义快照生成器
    CustomSnapshotGenerator *generator = [[CustomSnapshotGenerator alloc] init];
    UIImage *snapshot = [generator generateCustomSnapshot];
    
    if (snapshot) {
        // 保存快照供系统使用
        [self cacheSnapshot:snapshot];
    }
}

@end

方案五:性能监控和预警

// 性能监控系统
@interface PerformanceMonitor : NSObject
@property (nonatomic, strong) NSMutableArray *performanceMetrics;
@end

@implementation PerformanceMonitor

// 1. 监控主线程性能
- (void)monitorMainThreadPerformance {
    // 监控CPU使用率
    [self monitorCPUUsage];
    
    // 监控内存使用
    [self monitorMemoryUsage];
    
    // 监控渲染性能
    [self monitorRenderingPerformance];
}

// 2. CPU监控
- (void)monitorCPUUsage {
    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(checkCPUUsage) userInfo:nil repeats:YES];
}

- (void)checkCPUUsage {
    double cpuUsage = [self getMainThreadCPUUsage];
    
    if (cpuUsage > 80.0) { // 80%阈值
        NSLog(@"⚠️ 主线程CPU使用率过高: %.1f%%", cpuUsage);
        [self throttleBackgroundWork];
    }
}

// 3. 内存监控
- (void)monitorMemoryUsage {
    [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(checkMemoryUsage) userInfo:nil repeats:YES];
}

- (void)checkMemoryUsage {
    uint64_t memoryUsage = [self getAppMemoryUsage];
    
    if (memoryUsage > 100 * 1024 * 1024) { // 100MB阈值
        NSLog(@"⚠️ 内存使用过高: %llu MB", memoryUsage / 1024 / 1024);
        [self clearCaches];
    }
}

// 4. 预警系统
- (void)setupPerformanceAlerts {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(performanceAlert:)
                                                 name:@"PerformanceAlert"
                                               object:nil];
}

- (void)performanceAlert:(NSNotification *)notification {
    NSDictionary *info = notification.userInfo;
    NSString *alertType = info[@"type"];
    
    if ([alertType isEqualToString:@"SnapshotDeadlockImminent"]) {
        // 快照死锁预警,提前采取措施
        [self preventSnapshotDeadlock];
    }
}

- (void)preventSnapshotDeadlock {
    // 提前简化视图层次
    [self preemptivelySimplifyUI];
    
    // 暂停非关键操作
    [self pauseNonCriticalOperations];
    
    // 准备快速快照
    [self prepareForQuickSnapshot];
}

@end

预防措施总结

  1. 主线程优化:避免阻塞操作,使用异步处理
  2. 视图渲染优化:减少复杂图层和动画
  3. 快照预处理:在系统快照前准备应用状态
  4. 死锁检测:监控和自动恢复机制
  5. 性能监控:实时监控并预警性能问题

通过上述方案,可以显著减少因系统快照请求导致的死锁问题,提高应用稳定性。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容