| Differences between
and this patch
- a/Source/WebKit2/ChangeLog +33 lines
Lines 1-3 a/Source/WebKit2/ChangeLog_sec1
1
2016-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
1
2016-06-29  Gavin Barraclough  <barraclough@apple.com>
34
2016-06-29  Gavin Barraclough  <barraclough@apple.com>
2
35
3
        Cleanup ProcessAssertion RunInBackground management
36
        Cleanup ProcessAssertion RunInBackground management
- a/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h +3 lines
Lines 72-77 enum { a/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h_sec1
72
};
72
};
73
typedef uint32_t BKSProcessAssertionReason;
73
typedef uint32_t BKSProcessAssertionReason;
74
74
75
typedef void (^BKSProcessAssertionInvalidationHandler)(void);
75
typedef void (^BKSProcessAssertionAcquisitionHandler)(BOOL acquired);
76
typedef void (^BKSProcessAssertionAcquisitionHandler)(BOOL acquired);
76
77
77
@interface BKSProcessAssertion : NSObject
78
@interface BKSProcessAssertion : NSObject
Lines 80-85 typedef void (^BKSProcessAssertionAcquisitionHandler)(BOOL acquired); a/Source/WebKit2/Platform/spi/ios/AssertionServicesSPI.h_sec2
80
@interface BKSProcessAssertion ()
81
@interface BKSProcessAssertion ()
81
@property (nonatomic, assign) BKSProcessAssertionFlags flags;
82
@property (nonatomic, assign) BKSProcessAssertionFlags flags;
82
- (id)initWithPID:(pid_t)pid flags:(BKSProcessAssertionFlags)flags reason:(BKSProcessAssertionReason)reason name:(NSString *)name withHandler:(BKSProcessAssertionAcquisitionHandler)handler;
83
- (id)initWithPID:(pid_t)pid flags:(BKSProcessAssertionFlags)flags reason:(BKSProcessAssertionReason)reason name:(NSString *)name withHandler:(BKSProcessAssertionAcquisitionHandler)handler;
84
85
@property (nonatomic, copy) BKSProcessAssertionInvalidationHandler invalidationHandler;
83
- (void)invalidate;
86
- (void)invalidate;
84
@end
87
@end
85
88
- a/Source/WebKit2/UIProcess/ProcessAssertion.cpp -1 / +1 lines
Lines 30-36 a/Source/WebKit2/UIProcess/ProcessAssertion.cpp_sec1
30
30
31
namespace WebKit {
31
namespace WebKit {
32
32
33
ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState)
33
ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState, std::function<void()>)
34
    : m_assertionState(assertionState)
34
    : m_assertionState(assertionState)
35
{
35
{
36
}
36
}
- a/Source/WebKit2/UIProcess/ProcessAssertion.h -1 / +10 lines
Lines 26-31 a/Source/WebKit2/UIProcess/ProcessAssertion.h_sec1
26
#ifndef ProcessAssertion_h
26
#ifndef ProcessAssertion_h
27
#define ProcessAssertion_h
27
#define ProcessAssertion_h
28
28
29
#include <functional>
30
29
#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
31
#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
30
#include <wtf/RetainPtr.h>
32
#include <wtf/RetainPtr.h>
31
OBJC_CLASS BKSProcessAssertion;
33
OBJC_CLASS BKSProcessAssertion;
Lines 47-53 public: a/Source/WebKit2/UIProcess/ProcessAssertion.h_sec2
47
49
48
class ProcessAssertion {
50
class ProcessAssertion {
49
public:
51
public:
50
    ProcessAssertion(pid_t, AssertionState);
52
    ProcessAssertion(pid_t, AssertionState, std::function<void()> invalidationCallback = { });
51
    ~ProcessAssertion();
53
    ~ProcessAssertion();
52
54
53
    void setClient(ProcessAssertionClient& client) { m_client = &client; }
55
    void setClient(ProcessAssertionClient& client) { m_client = &client; }
Lines 56-64 public: a/Source/WebKit2/UIProcess/ProcessAssertion.h_sec3
56
    AssertionState state() const { return m_assertionState; }
58
    AssertionState state() const { return m_assertionState; }
57
    void setState(AssertionState);
59
    void setState(AssertionState);
58
60
61
#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
62
protected:
63
    enum class Validity { No, Yes, Unset };
64
    Validity validity() const { return m_validity; }
65
#endif
66
59
private:
67
private:
60
#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
68
#if PLATFORM(IOS) && !PLATFORM(IOS_SIMULATOR)
61
    RetainPtr<BKSProcessAssertion> m_assertion;
69
    RetainPtr<BKSProcessAssertion> m_assertion;
70
    Validity m_validity { Validity::Unset };
62
#endif
71
#endif
63
    AssertionState m_assertionState;
72
    AssertionState m_assertionState;
64
    ProcessAssertionClient* m_client { nullptr };
73
    ProcessAssertionClient* m_client { nullptr };
- a/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm -7 / +14 lines
Lines 143-163 static BKSProcessAssertionFlags flagsForState(AssertionState assertionState) a/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm_sec1
143
    }
143
    }
144
}
144
}
145
145
146
ProcessAssertion::ProcessAssertion(pid_t pid, AssertionState assertionState)
146
ProcessAssertion::ProcessAssertion(pid_t pid, AssertionState assertionState, std::function<void()> invalidationCallback)
147
    : m_assertionState(assertionState)
147
{
148
{
148
    m_assertionState = assertionState;
149
    
150
    BKSProcessAssertionAcquisitionHandler handler = ^(BOOL acquired) {
149
    BKSProcessAssertionAcquisitionHandler handler = ^(BOOL acquired) {
151
        if (!acquired) {
150
        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);
153
            ASSERT_NOT_REACHED();
152
            ASSERT_NOT_REACHED();
153
            m_validity = Validity::No;
154
            invalidationCallback();
154
        }
155
        }
155
    };
156
    };
156
    m_assertion = adoptNS([[BKSProcessAssertion alloc] initWithPID:pid flags:flagsForState(assertionState) reason:BKSProcessAssertionReasonExtension name:@"Web content visible" withHandler:handler]);
157
    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
    };
157
}
162
}
158
163
159
ProcessAssertion::~ProcessAssertion()
164
ProcessAssertion::~ProcessAssertion()
160
{
165
{
166
    m_assertion.get().invalidationHandler = nil;
167
161
    if (ProcessAssertionClient* client = this->client())
168
    if (ProcessAssertionClient* client = this->client())
162
        [[WKProcessAssertionBackgroundTaskManager shared] removeClient:*client];
169
        [[WKProcessAssertionBackgroundTaskManager shared] removeClient:*client];
163
    [m_assertion invalidate];
170
    [m_assertion invalidate];
Lines 174-180 void ProcessAssertion::setState(AssertionState assertionState) a/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm_sec2
174
181
175
void ProcessAndUIAssertion::updateRunInBackgroundCount()
182
void ProcessAndUIAssertion::updateRunInBackgroundCount()
176
{
183
{
177
    bool shouldHoldBackgroundAssertion = state() != AssertionState::Suspended;
184
    bool shouldHoldBackgroundAssertion = validity() != Validity::No && state() != AssertionState::Suspended;
178
185
179
    if (shouldHoldBackgroundAssertion) {
186
    if (shouldHoldBackgroundAssertion) {
180
        if (!m_isHoldingBackgroundAssertion)
187
        if (!m_isHoldingBackgroundAssertion)
Lines 188-194 void ProcessAndUIAssertion::updateRunInBackgroundCount() a/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm_sec3
188
}
195
}
189
196
190
ProcessAndUIAssertion::ProcessAndUIAssertion(pid_t pid, AssertionState assertionState)
197
ProcessAndUIAssertion::ProcessAndUIAssertion(pid_t pid, AssertionState assertionState)
191
    : ProcessAssertion(pid, assertionState)
198
    : ProcessAssertion(pid, assertionState, [this] { updateRunInBackgroundCount(); })
192
{
199
{
193
    updateRunInBackgroundCount();
200
    updateRunInBackgroundCount();
194
}
201
}
Lines 219-225 void ProcessAndUIAssertion::setClient(ProcessAssertionClient& newClient) a/Source/WebKit2/UIProcess/ios/ProcessAssertionIOS.mm_sec4
219
226
220
namespace WebKit {
227
namespace WebKit {
221
228
222
ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState)
229
ProcessAssertion::ProcessAssertion(pid_t, AssertionState assertionState, std::function<void()>)
223
    : m_assertionState(assertionState)
230
    : m_assertionState(assertionState)
224
{
231
{
225
}
232
}

Return to Bug 159280