Changeset 244761 in webkit


Ignore:
Timestamp:
Apr 29, 2019 3:40:48 PM (5 years ago)
Author:
Chris Dumez
Message:

[iOS] The UIProcess may get killed for trying to stay runnable in the background for more than 30 seconds
https://bugs.webkit.org/show_bug.cgi?id=197385
<rdar://problem/50001505>

Reviewed by Geoffrey Garen.

If the UIProcess holds a background assertion for itself for 30 seconds, the assertion's invalidation handler
will get called and it is our responsibility to release this assertion or the UIProcess will get killed by the
system. The logic in ProcessAssertion would normally do that but it would also happily try and re-take another
background process assertion shortly after the previous one expired (and before the UIProcess got suspended).
When doing so, the new background assertion would expire right away and we would get killed without its
invalidation handler getting called.

To address the issue, the logic in ProcessAssertion will now prevent taking a new background assertion after
one expires and until the application becomes foreground again.

  • UIProcess/ios/ProcessAssertionIOS.mm:

(-[WKProcessAssertionBackgroundTaskManager init]):
(-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):

Location:
trunk/Source/WebKit
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r244756 r244761  
     12019-04-29  Chris Dumez  <cdumez@apple.com>
     2
     3        [iOS] The UIProcess may get killed for trying to stay runnable in the background for more than 30 seconds
     4        https://bugs.webkit.org/show_bug.cgi?id=197385
     5        <rdar://problem/50001505>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        If the UIProcess holds a background assertion for itself for 30 seconds, the assertion's invalidation handler
     10        will get called and it is our responsibility to release this assertion or the UIProcess will get killed by the
     11        system. The logic in ProcessAssertion would normally do that but it would also happily try and re-take another
     12        background process assertion shortly after the previous one expired (and before the UIProcess got suspended).
     13        When doing so, the new background assertion would expire right away and we would get killed without its
     14        invalidation handler getting called.
     15
     16        To address the issue, the logic in ProcessAssertion will now prevent taking a new background assertion after
     17        one expires and until the application becomes foreground again.
     18
     19        * UIProcess/ios/ProcessAssertionIOS.mm:
     20        (-[WKProcessAssertionBackgroundTaskManager init]):
     21        (-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):
     22
    1232019-04-29  Alex Christensen  <achristensen@webkit.org>
    224
  • trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm

    r244707 r244761  
    5151    UIBackgroundTaskIdentifier _backgroundTask;
    5252    HashSet<ProcessAndUIAssertion*> _assertionsNeedingBackgroundTask;
     53    BOOL _assertionHasExpiredInTheBackground;
    5354}
    5455
     
    6768    _backgroundTask = UIBackgroundTaskInvalid;
    6869
     70    [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication] queue:nil usingBlock:^(NSNotification *) {
     71        _assertionHasExpiredInTheBackground = NO;
     72        [self _updateBackgroundTask];
     73    }];
     74
    6975    return self;
    7076}
     
    99105{
    100106    if (!_assertionsNeedingBackgroundTask.isEmpty() && _backgroundTask == UIBackgroundTaskInvalid) {
     107        if (_assertionHasExpiredInTheBackground) {
     108            RELEASE_LOG_ERROR(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager: Ignored request to start a background task because we're still in the background and the previous task expired", self);
     109            // Our invalidation handler would not get called if we tried to re-take a new background assertion at this point, and the UIProcess would get killed (rdar://problem/50001505).
     110            return;
     111        }
    101112        RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager - beginBackgroundTaskWithName", self);
    102113        _backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithName:@"com.apple.WebKit.ProcessAssertion" expirationHandler:^{
     
    110121                });
    111122            }
     123
     124            // Remember that the assertion has expired in the background so we do not try to re-take it until the application becomes foreground again.
     125            _assertionHasExpiredInTheBackground = YES;
    112126            [self _releaseBackgroundTask];
    113127        }];
Note: See TracChangeset for help on using the changeset viewer.