Changeset 202696 in webkit


Ignore:
Timestamp:
Jun 30, 2016 1:17:30 PM (8 years ago)
Author:
Chris Dumez
Message:

[iOS] Process suspension is prevented for 30 seconds after closing a tab
https://bugs.webkit.org/show_bug.cgi?id=159280
<rdar://problem/27014867>

Reviewed by Gavin Barraclough.

When closing a tab, ConnectionTerminationWatchdog takes a background
assertion on behalf of the WebContent process and only releases it
after 30 seconds, allowing for the WebContent process to exit cleanly
without worrying about getting suspended too early.

However, the child process normally exits much sooner than this and
we end up holding a process assertion for no reason for a full 30
seconds anyway. This patch addresses the issue by registering an
invalidation handler with the BKSProcessAssertion and releasing our
our assertion in such case. The invalidation handler gets called
as soon as the child process exits.

  • Platform/spi/ios/AssertionServicesSPI.h:
  • UIProcess/ProcessAssertion.cpp:

(WebKit::ProcessAssertion::ProcessAssertion):

  • UIProcess/ProcessAssertion.h:

(WebKit::ProcessAssertion::ProcessAssertion):
(WebKit::ProcessAssertion::validity):

  • UIProcess/ios/ProcessAssertionIOS.mm:

(WebKit::ProcessAssertion::ProcessAssertion):
(WebKit::ProcessAssertion::~ProcessAssertion):
(WebKit::ProcessAndUIAssertion::updateRunInBackgroundCount):
(WebKit::ProcessAndUIAssertion::ProcessAndUIAssertion):
(WebKit::ProcessAssertion::setState): Deleted.

Location:
trunk/Source/WebKit2
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r202695 r202696  
     12016-06-30  Chris Dumez  <cdumez@apple.com>
     2
     3        [iOS] Process suspension is prevented for 30 seconds after closing a tab
     4        https://bugs.webkit.org/show_bug.cgi?id=159280
     5        <rdar://problem/27014867>
     6
     7        Reviewed by Gavin Barraclough.
     8
     9        When closing a tab, ConnectionTerminationWatchdog takes a background
     10        assertion on behalf of the WebContent process and only releases it
     11        after 30 seconds, allowing for the WebContent process to exit cleanly
     12        without worrying about getting suspended too early.
     13
     14        However, the child process normally exits much sooner than this and
     15        we end up holding a process assertion for no reason for a full 30
     16        seconds anyway. This patch addresses the issue by registering an
     17        invalidation handler with the BKSProcessAssertion and releasing our
     18        our assertion in such case. The invalidation handler gets called
     19        as soon as the child process exits.
     20
     21        * Platform/spi/ios/AssertionServicesSPI.h:
     22        * UIProcess/ProcessAssertion.cpp:
     23        (WebKit::ProcessAssertion::ProcessAssertion):
     24        * UIProcess/ProcessAssertion.h:
     25        (WebKit::ProcessAssertion::ProcessAssertion):
     26        (WebKit::ProcessAssertion::validity):
     27        * UIProcess/ios/ProcessAssertionIOS.mm:
     28        (WebKit::ProcessAssertion::ProcessAssertion):
     29        (WebKit::ProcessAssertion::~ProcessAssertion):
     30        (WebKit::ProcessAndUIAssertion::updateRunInBackgroundCount):
     31        (WebKit::ProcessAndUIAssertion::ProcessAndUIAssertion):
     32        (WebKit::ProcessAssertion::setState): Deleted.
     33
    1342016-06-30  Tim Horton  <timothy_horton@apple.com>
    235
  • trunk/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h

    r187609 r202696  
    7373typedef uint32_t BKSProcessAssertionReason;
    7474
     75typedef void (^BKSProcessAssertionInvalidationHandler)(void);
    7576typedef void (^BKSProcessAssertionAcquisitionHandler)(BOOL acquired);
    7677
     
    8182@property (nonatomic, assign) BKSProcessAssertionFlags flags;
    8283- (id)initWithPID:(pid_t)pid flags:(BKSProcessAssertionFlags)flags reason:(BKSProcessAssertionReason)reason name:(NSString *)name withHandler:(BKSProcessAssertionAcquisitionHandler)handler;
     84
     85@property (nonatomic, copy) BKSProcessAssertionInvalidationHandler invalidationHandler;
    8386- (void)invalidate;
    8487@end
  • trunk/Source/WebKit2/UIProcess/ProcessAssertion.cpp

    r184105 r202696  
    3131namespace WebKit {
    3232
    33 ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState)
     33ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState, std::function<void()>)
    3434    : m_assertionState(assertionState)
    3535{
  • trunk/Source/WebKit2/UIProcess/ProcessAssertion.h

    r202690 r202696  
    2727#define ProcessAssertion_h
    2828
     29#include <functional>
     30
    2931#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
    3032#include <wtf/RetainPtr.h>
     
    4850class ProcessAssertion {
    4951public:
    50     ProcessAssertion(pid_t, AssertionState);
     52    ProcessAssertion(pid_t, AssertionState, std::function<void()> invalidationCallback = { });
    5153    ~ProcessAssertion();
    5254
     
    5759    void setState(AssertionState);
    5860
     61#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
     62protected:
     63    enum class Validity { No, Yes, Unset };
     64    Validity validity() const { return m_validity; }
     65#endif
     66
    5967private:
    6068#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
    6169    RetainPtr<BKSProcessAssertion> m_assertion;
     70    Validity m_validity { Validity::Unset };
    6271#endif
    6372    AssertionState m_assertionState;
  • trunk/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm

    r202690 r202696  
    144144}
    145145
    146 ProcessAssertion::ProcessAssertion(pid_t pid, AssertionState assertionState)
    147 {
    148     m_assertionState = assertionState;
    149    
     146ProcessAssertion::ProcessAssertion(pid_t pid, AssertionState assertionState, std::function<void()> invalidationCallback)
     147    : m_assertionState(assertionState)
     148{
    150149    BKSProcessAssertionAcquisitionHandler handler = ^(BOOL acquired) {
    151150        if (!acquired) {
    152             LOG_ERROR("Unable to acquire assertion for process %d", pid);
     151            LOG_ALWAYS_ERROR(true, "Unable to acquire assertion for process %d", pid);
    153152            ASSERT_NOT_REACHED();
     153            m_validity = Validity::No;
     154            invalidationCallback();
    154155        }
    155156    };
    156157    m_assertion = adoptNS([[BKSProcessAssertion alloc] initWithPID:pid flags:flagsForState(assertionState) reason:BKSProcessAssertionReasonExtension name:@"Web content visible" withHandler:handler]);
     158    m_assertion.get().invalidationHandler = ^() {
     159        m_validity = Validity::No;
     160        invalidationCallback();
     161    };
    157162}
    158163
    159164ProcessAssertion::~ProcessAssertion()
    160165{
     166    m_assertion.get().invalidationHandler = nil;
     167
    161168    if (ProcessAssertionClient* client = this->client())
    162169        [[WKProcessAssertionBackgroundTaskManager shared] removeClient:*client];
     
    175182void ProcessAndUIAssertion::updateRunInBackgroundCount()
    176183{
    177     bool shouldHoldBackgroundAssertion = state() != AssertionState::Suspended;
     184    bool shouldHoldBackgroundAssertion = validity() != Validity::No && state() != AssertionState::Suspended;
    178185
    179186    if (shouldHoldBackgroundAssertion) {
     
    189196
    190197ProcessAndUIAssertion::ProcessAndUIAssertion(pid_t pid, AssertionState assertionState)
    191     : ProcessAssertion(pid, assertionState)
     198    : ProcessAssertion(pid, assertionState, [this] { updateRunInBackgroundCount(); })
    192199{
    193200    updateRunInBackgroundCount();
     
    220227namespace WebKit {
    221228
    222 ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState)
     229ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState, std::function<void()>)
    223230    : m_assertionState(assertionState)
    224231{
Note: See TracChangeset for help on using the changeset viewer.