Title: [276969] trunk/Source/WebKit
Revision
276969
Author
cdu...@apple.com
Date
2021-05-04 11:04:16 -0700 (Tue, 04 May 2021)

Log Message

[iOS] Use async API to take RunningBoard assertions
https://bugs.webkit.org/show_bug.cgi?id=225324
<rdar://76972252>

Reviewed by Geoffrey Garen.

Use async [RBSAssertion acquireWithInvalidationHandler:] API to take process assertions
instead of the synchronous [RBSAssertion acquireWithError:] API. This avoids risking
hanging the main thread for too long.

Note that [RBSAssertion isValid] returns false until the assertion is taken so I am
using our own "isValid" boolean to indicate if the RBSAssertion was invalidated or
or not. We use this flag to decide if we need to take the assertion again. We wouldn't
want to re-take the assertion simply because it is still in the process of being
acquired.

* UIProcess/ProcessAssertion.cpp:
(WebKit::ProcessAssertion::isValid const): Deleted.
* UIProcess/ProcessAssertion.h:
(WebKit::ProcessAssertion::isValid const):
* UIProcess/ios/ProcessAssertionIOS.mm:
(-[WKProcessAssertionBackgroundTaskManager init]):
(-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):
(-[WKProcessAssertionBackgroundTaskManager assertion:didInvalidateWithError:]):
(-[WKProcessAssertionBackgroundTaskManager _releaseBackgroundTask]):
(WebKit::ProcessAssertion::ProcessAssertion):
(WebKit::ProcessAssertion::~ProcessAssertion):
(WebKit::ProcessAssertion::processAssertionWasInvalidated):
(-[WKProcessAssertionBackgroundTaskManager _hasBackgroundTask]): Deleted.
(-[WKRBSAssertionDelegate dealloc]): Deleted.
(-[WKRBSAssertionDelegate assertionWillInvalidate:]): Deleted.
(-[WKRBSAssertionDelegate assertion:didInvalidateWithError:]): Deleted.
(WebKit::ProcessAssertion::isValid const): Deleted.

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (276968 => 276969)


--- trunk/Source/WebKit/ChangeLog	2021-05-04 17:41:52 UTC (rev 276968)
+++ trunk/Source/WebKit/ChangeLog	2021-05-04 18:04:16 UTC (rev 276969)
@@ -1,3 +1,39 @@
+2021-05-04  Chris Dumez  <cdu...@apple.com>
+
+        [iOS] Use async API to take RunningBoard assertions
+        https://bugs.webkit.org/show_bug.cgi?id=225324
+        <rdar://76972252>
+
+        Reviewed by Geoffrey Garen.
+
+        Use async [RBSAssertion acquireWithInvalidationHandler:] API to take process assertions
+        instead of the synchronous [RBSAssertion acquireWithError:] API. This avoids risking
+        hanging the main thread for too long.
+
+        Note that [RBSAssertion isValid] returns false until the assertion is taken so I am
+        using our own "isValid" boolean to indicate if the RBSAssertion was invalidated or
+        or not. We use this flag to decide if we need to take the assertion again. We wouldn't
+        want to re-take the assertion simply because it is still in the process of being
+        acquired.
+
+        * UIProcess/ProcessAssertion.cpp:
+        (WebKit::ProcessAssertion::isValid const): Deleted.
+        * UIProcess/ProcessAssertion.h:
+        (WebKit::ProcessAssertion::isValid const):
+        * UIProcess/ios/ProcessAssertionIOS.mm:
+        (-[WKProcessAssertionBackgroundTaskManager init]):
+        (-[WKProcessAssertionBackgroundTaskManager _updateBackgroundTask]):
+        (-[WKProcessAssertionBackgroundTaskManager assertion:didInvalidateWithError:]):
+        (-[WKProcessAssertionBackgroundTaskManager _releaseBackgroundTask]):
+        (WebKit::ProcessAssertion::ProcessAssertion):
+        (WebKit::ProcessAssertion::~ProcessAssertion):
+        (WebKit::ProcessAssertion::processAssertionWasInvalidated):
+        (-[WKProcessAssertionBackgroundTaskManager _hasBackgroundTask]): Deleted.
+        (-[WKRBSAssertionDelegate dealloc]): Deleted.
+        (-[WKRBSAssertionDelegate assertionWillInvalidate:]): Deleted.
+        (-[WKRBSAssertionDelegate assertion:didInvalidateWithError:]): Deleted.
+        (WebKit::ProcessAssertion::isValid const): Deleted.
+
 2021-05-04  Jim Mason  <jma...@ibinx.com>
 
         [GTK] segmentation fault in WebKit::IconDatabase::loadIconForPageURL

Modified: trunk/Source/WebKit/Platform/spi/ios/RunningBoardServicesSPI.h (276968 => 276969)


--- trunk/Source/WebKit/Platform/spi/ios/RunningBoardServicesSPI.h	2021-05-04 17:41:52 UTC (rev 276968)
+++ trunk/Source/WebKit/Platform/spi/ios/RunningBoardServicesSPI.h	2021-05-04 18:04:16 UTC (rev 276969)
@@ -55,11 +55,14 @@
 + (RBSTarget *)currentProcess;
 @end
 
+@class RBSAssertion;
 @protocol RBSAssertionObserving;
+typedef void (^RBSAssertionInvalidationHandler)(RBSAssertion *assertion, NSError *error);
 
 @interface RBSAssertion : NSObject
 - (instancetype)initWithExplanation:(NSString *)explanation target:(RBSTarget *)target attributes:(NSArray <RBSAttribute *> *)attributes;
 - (BOOL)acquireWithError:(NSError **)error;
+- (void)acquireWithInvalidationHandler:(nullable RBSAssertionInvalidationHandler)handler;
 - (void)invalidate;
 - (void)addObserver:(id <RBSAssertionObserving>)observer;
 - (void)removeObserver:(id <RBSAssertionObserving>)observer;

Modified: trunk/Source/WebKit/UIProcess/ProcessAssertion.h (276968 => 276969)


--- trunk/Source/WebKit/UIProcess/ProcessAssertion.h	2021-05-04 17:41:52 UTC (rev 276968)
+++ trunk/Source/WebKit/UIProcess/ProcessAssertion.h	2021-05-04 18:04:16 UTC (rev 276969)
@@ -38,7 +38,6 @@
 #include <wtf/RetainPtr.h>
 
 OBJC_CLASS RBSAssertion;
-OBJC_CLASS WKRBSAssertionDelegate;
 #endif // PLATFORM(IOS_FAMILY)
 
 namespace WebKit {
@@ -74,7 +73,7 @@
     const ProcessID m_pid;
 #if PLATFORM(IOS_FAMILY)
     RetainPtr<RBSAssertion> m_rbsAssertion;
-    RetainPtr<WKRBSAssertionDelegate> m_delegate;
+    bool m_wasInvalidated { false };
 #endif
     Function<void()> m_invalidationHandler;
 };

Modified: trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm (276968 => 276969)


--- trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm	2021-05-04 17:41:52 UTC (rev 276968)
+++ trunk/Source/WebKit/UIProcess/ios/ProcessAssertionIOS.mm	2021-05-04 18:04:16 UTC (rev 276969)
@@ -63,6 +63,7 @@
 @implementation WKProcessAssertionBackgroundTaskManager
 {
     RetainPtr<RBSAssertion> _backgroundTask;
+    std::atomic<bool> _backgroundTaskWasInvalidated;
     WeakHashSet<ProcessAndUIAssertion> _assertionsNeedingBackgroundTask;
     dispatch_block_t _pendingTaskReleaseTask;
 }
@@ -159,7 +160,7 @@
 
 - (void)_updateBackgroundTask
 {
-    if (!_assertionsNeedingBackgroundTask.computesEmpty() && ![self _hasBackgroundTask]) {
+    if (!_assertionsNeedingBackgroundTask.computesEmpty() && (![self _hasBackgroundTask] || _backgroundTaskWasInvalidated)) {
         if (processHasActiveRunTimeLimitation()) {
             RELEASE_LOG(ProcessSuspension, "%p - WKProcessAssertionBackgroundTaskManager: Ignored request to start a new background task because RunningBoard has already started the expiration timer", self);
             return;
@@ -169,12 +170,9 @@
         RBSDomainAttribute *domainAttribute = [RBSDomainAttribute attributeWithDomain:@"com.apple.common" name:@"FinishTaskInterruptable"];
         _backgroundTask = adoptNS([[RBSAssertion alloc] initWithExplanation:@"WebKit UIProcess background task" target:target attributes:@[domainAttribute]]);
         [_backgroundTask addObserver:self];
-
-        NSError *acquisitionError = nil;
-        if (![_backgroundTask acquireWithError:&acquisitionError])
-            RELEASE_LOG_ERROR(ProcessSuspension, "WKProcessAssertionBackgroundTaskManager: Failed to acquire FinishTaskInterruptable assertion for own process, error: %{public}@", acquisitionError);
-        else
-            RELEASE_LOG(ProcessSuspension, "WKProcessAssertionBackgroundTaskManager: Successfully took a FinishTaskInterruptable assertion for own process");
+        _backgroundTaskWasInvalidated = false;
+        [_backgroundTask acquireWithInvalidationHandler:nil];
+        RELEASE_LOG(ProcessSuspension, "WKProcessAssertionBackgroundTaskManager: Took a FinishTaskInterruptable assertion for own process");
     } else if (_assertionsNeedingBackgroundTask.computesEmpty()) {
         // Release the background task asynchronously because releasing the background task may destroy the ProcessThrottler and we don't
         // want it to get destroyed while in the middle of updating its assertion.
@@ -195,6 +193,7 @@
 {
     ASSERT(assertion == _backgroundTask.get());
     RELEASE_LOG_ERROR(ProcessSuspension, "WKProcessAssertionBackgroundTaskManager: FinishTaskInterruptable assertion was invalidated, error: %{public}@", error);
+    _backgroundTaskWasInvalidated = true;
 }
 
 - (void)_handleBackgroundTaskExpiration
@@ -245,36 +244,6 @@
 
 @end
 
-typedef void(^RBSAssertionInvalidationCallbackType)();
-
-@interface WKRBSAssertionDelegate : NSObject<RBSAssertionObserving>
-@property (copy) RBSAssertionInvalidationCallbackType invalidationCallback;
-@end
-
-@implementation WKRBSAssertionDelegate
-- (void)dealloc
-{
-    [_invalidationCallback release];
-    [super dealloc];
-}
-
-- (void)assertionWillInvalidate:(RBSAssertion *)assertion
-{
-    RELEASE_LOG(ProcessSuspension, "%p - WKRBSAssertionDelegate: assertionWillInvalidate", self);
-}
-
-- (void)assertion:(RBSAssertion *)assertion didInvalidateWithError:(NSError *)error
-{
-    RELEASE_LOG(ProcessSuspension, "%p - WKRBSAssertionDelegate: assertion was invalidated, error: %{public}@", error, self);
-
-    RunLoop::main().dispatch([weakSelf = WeakObjCPtr<WKRBSAssertionDelegate>(self)] {
-        auto strongSelf = weakSelf.get();
-        if (strongSelf && strongSelf.get().invalidationCallback)
-            strongSelf.get().invalidationCallback();
-    });
-}
-@end
-
 namespace WebKit {
 
 static NSString *runningBoardNameForAssertionType(ProcessAssertionType assertionType)
@@ -307,23 +276,16 @@
     RBSTarget *target = [RBSTarget targetWithPid:pid];
     RBSDomainAttribute *domainAttribute = [RBSDomainAttribute attributeWithDomain:@"com.apple.webkit" name:runningBoardAssertionName];
     m_rbsAssertion = adoptNS([[RBSAssertion alloc] initWithExplanation:reason target:target attributes:@[domainAttribute]]);
+    [m_rbsAssertion acquireWithInvalidationHandler:[weakThis = makeWeakPtr(*this), pid, runningBoardAssertionName = retainPtr(runningBoardAssertionName)](RBSAssertion *assertion, NSError *error) mutable {
+        callOnMainRunLoop([weakThis = WTFMove(weakThis), pid, runningBoardAssertionName = WTFMove(runningBoardAssertionName), error = retainPtr(error)] {
+            if (!weakThis)
+                return;
+            RELEASE_LOG(ProcessSuspension, "%p - ProcessAssertion() RBS %{public}@ assertion for process with PID=%d was invalidated, error: %{public}@", weakThis.get(), runningBoardAssertionName.get(), pid, error.get());
+            weakThis->processAssertionWasInvalidated();
+        });
+    }];
 
-    m_delegate = adoptNS([[WKRBSAssertionDelegate alloc] init]);
-    [m_rbsAssertion addObserver:m_delegate.get()];
-    m_delegate.get().invalidationCallback = ^{
-        RELEASE_LOG(ProcessSuspension, "%p - ProcessAssertion() RBS %{public}@ assertion for process with PID=%d was invalidated", this, runningBoardAssertionName, pid);
-        processAssertionWasInvalidated();
-    };
-
-    NSError *acquisitionError = nil;
-    if (![m_rbsAssertion acquireWithError:&acquisitionError]) {
-        RELEASE_LOG_ERROR(ProcessSuspension, "%p - ProcessAssertion: Failed to acquire RBS %{public}@ assertion '%{public}s' for process with PID=%d, error: %{public}@", this, runningBoardAssertionName, reason.utf8().data(), pid, acquisitionError);
-        RunLoop::main().dispatch([weakThis = makeWeakPtr(*this)] {
-            if (weakThis)
-                weakThis->processAssertionWasInvalidated();
-        });
-    } else
-        RELEASE_LOG(ProcessSuspension, "%p - ProcessAssertion: Successfully took RBS %{public}@ assertion '%{public}s' for process with PID=%d", this, runningBoardAssertionName, reason.utf8().data(), pid);
+    RELEASE_LOG(ProcessSuspension, "%p - ProcessAssertion: Took RBS %{public}@ assertion '%{public}s' for process with PID=%d", this, runningBoardAssertionName, reason.utf8().data(), pid);
 }
 
 ProcessAssertion::~ProcessAssertion()
@@ -330,12 +292,8 @@
 {
     RELEASE_LOG(ProcessSuspension, "%p - ~ProcessAssertion() Releasing process assertion for process with PID=%d", this, m_pid);
 
-    if (m_rbsAssertion) {
-        m_delegate.get().invalidationCallback = nil;
-        [m_rbsAssertion removeObserver:m_delegate.get()];
-        m_delegate = nil;
+    if (m_rbsAssertion)
         [m_rbsAssertion invalidate];
-    }
 }
 
 void ProcessAssertion::processAssertionWasInvalidated()
@@ -343,6 +301,7 @@
     ASSERT(RunLoop::isMain());
     RELEASE_LOG(ProcessSuspension, "%p - ProcessAssertion::processAssertionWasInvalidated() PID=%d", this, m_pid);
 
+    m_wasInvalidated = true;
     if (m_invalidationHandler)
         m_invalidationHandler();
 }
@@ -349,7 +308,7 @@
 
 bool ProcessAssertion::isValid() const
 {
-    return m_rbsAssertion && m_rbsAssertion.get().valid;
+    return m_rbsAssertion && !m_wasInvalidated;
 }
 
 void ProcessAndUIAssertion::updateRunInBackgroundCount()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to