Commit c56ae86a authored by Michael Lippautz's avatar Michael Lippautz Committed by Commit Bot

Keep WorkerGlobalScope wrapper alive as long as its context is alive

We previously only kept the wrapper alive as long as the scope had
timers attached. This requires us to kept explicit hidden references to
event listeners to prevent them from being garbage collected.

Relying on wrapper tracing requires us to keep the scope alive as long
as its context is alive.

This is a dependency for
  https://chromium-review.googlesource.com/c/576472/

Bug: 
Change-Id: I82c177f6e93a7ed15697e574f4e0e001957dff7a
Reviewed-on: https://chromium-review.googlesource.com/584875
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Reviewed-by: default avatarHiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491363}
parent 07615e04
...@@ -25,9 +25,8 @@ function runTests() ...@@ -25,9 +25,8 @@ function runTests()
// Orphan our worker (no more references to it) and wait for it to exit. // Orphan our worker (no more references to it) and wait for it to exit.
worker.onmessage = 0; worker.onmessage = 0;
worker.terminate();
worker = 0; worker = 0;
// Allocating a Date object seems to scramble the stack and force the worker object to get GC'd.
new Date();
waitUntilWorkerThreadsExit(orphanedWorkerExited); waitUntilWorkerThreadsExit(orphanedWorkerExited);
} }
} }
...@@ -51,10 +50,8 @@ function orphanedWorkerExited() ...@@ -51,10 +50,8 @@ function orphanedWorkerExited()
// Orphan our worker (no more references to it) and wait for it to exit. // Orphan our worker (no more references to it) and wait for it to exit.
worker.onmessage = 0; worker.onmessage = 0;
worker.terminate();
worker = 0; worker = 0;
// For some reason, the worker object does not get GC'd unless we allocate a new object here.
// The conjecture is that there's a value on the stack that appears to point to the worker which this clobbers.
new Date();
waitUntilWorkerThreadsExit(orphanedTimeoutWorkerExited); waitUntilWorkerThreadsExit(orphanedTimeoutWorkerExited);
} }
} }
......
...@@ -40,10 +40,6 @@ DOMTimer* DOMTimerCoordinator::RemoveTimeoutByID(int timeout_id) { ...@@ -40,10 +40,6 @@ DOMTimer* DOMTimerCoordinator::RemoveTimeoutByID(int timeout_id) {
return removed_timer; return removed_timer;
} }
bool DOMTimerCoordinator::HasInstalledTimeout() const {
return !timers_.IsEmpty();
}
DEFINE_TRACE(DOMTimerCoordinator) { DEFINE_TRACE(DOMTimerCoordinator) {
visitor->Trace(timers_); visitor->Trace(timers_);
} }
......
...@@ -38,8 +38,6 @@ class DOMTimerCoordinator { ...@@ -38,8 +38,6 @@ class DOMTimerCoordinator {
// destroy the timer. // destroy the timer.
DOMTimer* RemoveTimeoutByID(int id); DOMTimer* RemoveTimeoutByID(int id);
bool HasInstalledTimeout() const;
// Timers created during the execution of other timers, and // Timers created during the execution of other timers, and
// repeating timers, are throttled. Timer nesting level tracks the // repeating timers, are throttled. Timer nesting level tracks the
// number of linked timers or repetitions of a timer. See // number of linked timers or repetitions of a timer. See
......
...@@ -24,19 +24,6 @@ ...@@ -24,19 +24,6 @@
namespace blink { namespace blink {
namespace {
// These are chosen by trial-and-error. Making these intervals smaller causes
// test flakiness. The main thread needs to wait until message confirmation and
// activity report separately. If the intervals are very short, they are
// notified to the main thread almost at the same time and the thread may miss
// the second notification.
constexpr double kDefaultIntervalInSec = 0.01;
constexpr double kNextIntervalInSec = 0.01;
constexpr double kMaxIntervalInSec = 0.02;
} // namespace
class DedicatedWorkerThreadForTest final : public DedicatedWorkerThread { class DedicatedWorkerThreadForTest final : public DedicatedWorkerThread {
public: public:
DedicatedWorkerThreadForTest(InProcessWorkerObjectProxy& worker_object_proxy) DedicatedWorkerThreadForTest(InProcessWorkerObjectProxy& worker_object_proxy)
...@@ -96,9 +83,6 @@ class InProcessWorkerObjectProxyForTest final ...@@ -96,9 +83,6 @@ class InProcessWorkerObjectProxyForTest final
ParentFrameTaskRunners* parent_frame_task_runners) ParentFrameTaskRunners* parent_frame_task_runners)
: InProcessWorkerObjectProxy(messaging_proxy, parent_frame_task_runners), : InProcessWorkerObjectProxy(messaging_proxy, parent_frame_task_runners),
reported_features_(static_cast<int>(WebFeature::kNumberOfFeatures)) { reported_features_(static_cast<int>(WebFeature::kNumberOfFeatures)) {
default_interval_in_sec_ = kDefaultIntervalInSec;
next_interval_in_sec_ = kNextIntervalInSec;
max_interval_in_sec_ = kMaxIntervalInSec;
} }
void CountFeature(WebFeature feature) override { void CountFeature(WebFeature feature) override {
...@@ -131,7 +115,6 @@ class InProcessWorkerMessagingProxyForTest ...@@ -131,7 +115,6 @@ class InProcessWorkerMessagingProxyForTest
} }
~InProcessWorkerMessagingProxyForTest() override { ~InProcessWorkerMessagingProxyForTest() override {
EXPECT_FALSE(blocking_);
} }
void StartWithSourceCode(const String& source) { void StartWithSourceCode(const String& source) {
...@@ -153,49 +136,10 @@ class InProcessWorkerMessagingProxyForTest ...@@ -153,49 +136,10 @@ class InProcessWorkerMessagingProxyForTest
CreateBackingThreadStartupData(nullptr /* isolate */), script_url); CreateBackingThreadStartupData(nullptr /* isolate */), script_url);
} }
enum class Notification {
kMessageConfirmed,
kPendingActivityReported,
};
// Blocks the main thread until some event is notified.
Notification WaitForNotification() {
EXPECT_TRUE(IsMainThread());
DCHECK(!blocking_);
if (events_.IsEmpty()) {
blocking_ = true;
testing::EnterRunLoop();
DCHECK(!blocking_);
}
return events_.TakeFirst();
}
void ConfirmMessageFromWorkerObject() override {
EXPECT_TRUE(IsMainThread());
InProcessWorkerMessagingProxy::ConfirmMessageFromWorkerObject();
events_.push_back(Notification::kMessageConfirmed);
if (blocking_)
testing::ExitRunLoop();
blocking_ = false;
}
void PendingActivityFinished() override {
EXPECT_TRUE(IsMainThread());
InProcessWorkerMessagingProxy::PendingActivityFinished();
events_.push_back(Notification::kPendingActivityReported);
if (blocking_)
testing::ExitRunLoop();
blocking_ = false;
}
DedicatedWorkerThreadForTest* GetDedicatedWorkerThread() { DedicatedWorkerThreadForTest* GetDedicatedWorkerThread() {
return static_cast<DedicatedWorkerThreadForTest*>(GetWorkerThread()); return static_cast<DedicatedWorkerThreadForTest*>(GetWorkerThread());
} }
unsigned UnconfirmedMessageCount() const {
return unconfirmed_message_count_;
}
DEFINE_INLINE_VIRTUAL_TRACE() { DEFINE_INLINE_VIRTUAL_TRACE() {
visitor->Trace(mock_worker_thread_lifecycle_observer_); visitor->Trace(mock_worker_thread_lifecycle_observer_);
InProcessWorkerMessagingProxy::Trace(visitor); InProcessWorkerMessagingProxy::Trace(visitor);
...@@ -224,13 +168,8 @@ class InProcessWorkerMessagingProxyForTest ...@@ -224,13 +168,8 @@ class InProcessWorkerMessagingProxyForTest
Member<MockWorkerThreadLifecycleObserver> Member<MockWorkerThreadLifecycleObserver>
mock_worker_thread_lifecycle_observer_; mock_worker_thread_lifecycle_observer_;
RefPtr<SecurityOrigin> security_origin_; RefPtr<SecurityOrigin> security_origin_;
WTF::Deque<Notification> events_;
bool blocking_ = false;
}; };
using Notification = InProcessWorkerMessagingProxyForTest::Notification;
class DedicatedWorkerTest : public ::testing::Test { class DedicatedWorkerTest : public ::testing::Test {
public: public:
DedicatedWorkerTest() {} DedicatedWorkerTest() {}
...@@ -266,142 +205,14 @@ class DedicatedWorkerTest : public ::testing::Test { ...@@ -266,142 +205,14 @@ class DedicatedWorkerTest : public ::testing::Test {
Persistent<InProcessWorkerMessagingProxyForTest> worker_messaging_proxy_; Persistent<InProcessWorkerMessagingProxyForTest> worker_messaging_proxy_;
}; };
TEST_F(DedicatedWorkerTest, PendingActivity_NoActivity) { TEST_F(DedicatedWorkerTest, PendingActivity_NoActivityAfterContextDestroyed) {
const String source_code = "// Do nothing"; const String source_code = "// Do nothing";
WorkerMessagingProxy()->StartWithSourceCode(source_code); WorkerMessagingProxy()->StartWithSourceCode(source_code);
// Worker initialization should be counted as a pending activity.
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
// There should be no pending activities after the initialization.
EXPECT_EQ(Notification::kPendingActivityReported,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity());
}
TEST_F(DedicatedWorkerTest, PendingActivity_SetTimeout) {
// Start an oneshot timer on initial script evaluation.
const String source_code = "setTimeout(function() {}, 0);";
WorkerMessagingProxy()->StartWithSourceCode(source_code);
// Worker initialization should be counted as a pending activity.
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
// The timer is fired soon and there should be no pending activities after
// that.
EXPECT_EQ(Notification::kPendingActivityReported,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity());
}
TEST_F(DedicatedWorkerTest, PendingActivity_SetInterval) {
// Start a repeated timer on initial script evaluation, and stop it when a
// message is received. The timer needs a non-zero delay or else worker
// activities would not run.
const String source_code =
"var id = setInterval(function() {}, 50);"
"addEventListener('message', function(event) { clearInterval(id); });";
WorkerMessagingProxy()->StartWithSourceCode(source_code);
// Worker initialization should be counted as a pending activity.
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
// Stop the timer.
DispatchMessageEvent();
EXPECT_EQ(1u, WorkerMessagingProxy()->UnconfirmedMessageCount());
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
EXPECT_EQ(Notification::kMessageConfirmed,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_EQ(0u, WorkerMessagingProxy()->UnconfirmedMessageCount());
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
// There should be no pending activities after the timer is stopped.
EXPECT_EQ(Notification::kPendingActivityReported,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity());
}
TEST_F(DedicatedWorkerTest, PendingActivity_SetTimeoutOnMessageEvent) {
// Start an oneshot timer on a message event.
const String source_code =
"addEventListener('message', function(event) {"
" setTimeout(function() {}, 0);"
"});";
WorkerMessagingProxy()->StartWithSourceCode(source_code);
// Worker initialization should be counted as a pending activity.
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
EXPECT_EQ(Notification::kPendingActivityReported,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity());
// A message starts the oneshot timer that is counted as a pending activity.
DispatchMessageEvent();
EXPECT_EQ(1u, WorkerMessagingProxy()->UnconfirmedMessageCount());
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
EXPECT_EQ(Notification::kMessageConfirmed,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_EQ(0u, WorkerMessagingProxy()->UnconfirmedMessageCount());
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
// The timer is fired soon and there should be no pending activities after
// that.
EXPECT_EQ(Notification::kPendingActivityReported,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity());
}
TEST_F(DedicatedWorkerTest, PendingActivity_SetIntervalOnMessageEvent) {
// Start a repeated timer on a message event, and stop it when another
// message is received. The timer needs a non-zero delay or else worker
// activities would not run.
const String source_code =
"var count = 0;"
"var id;"
"addEventListener('message', function(event) {"
" if (count++ == 0) {"
" id = setInterval(function() {}, 50);"
" } else {"
" clearInterval(id);"
" }"
"});";
WorkerMessagingProxy()->StartWithSourceCode(source_code);
// Worker initialization should be counted as a pending activity.
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
EXPECT_EQ(Notification::kPendingActivityReported,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity());
// The first message event sets the active timer that is counted as a
// pending activity.
DispatchMessageEvent();
EXPECT_EQ(1u, WorkerMessagingProxy()->UnconfirmedMessageCount());
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
EXPECT_EQ(Notification::kMessageConfirmed,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_EQ(0u, WorkerMessagingProxy()->UnconfirmedMessageCount());
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
// Run the message loop for a while to make sure the timer is counted as a
// pending activity until it's stopped. The delay is equal to the max
// interval so that the pending activity timer may be able to have a chance
// to run before the next expectation check.
constexpr TimeDelta kDelay = TimeDelta::FromSecondsD(kMaxIntervalInSec);
testing::RunDelayedTasks(kDelay);
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
// Stop the timer.
DispatchMessageEvent();
EXPECT_EQ(1u, WorkerMessagingProxy()->UnconfirmedMessageCount());
EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity()); EXPECT_TRUE(WorkerMessagingProxy()->HasPendingActivity());
EXPECT_EQ(Notification::kMessageConfirmed,
WorkerMessagingProxy()->WaitForNotification());
EXPECT_EQ(0u, WorkerMessagingProxy()->UnconfirmedMessageCount());
// There should be no pending activities after the timer is stopped. // Destroying the context should result in no pending activities.
EXPECT_EQ(Notification::kPendingActivityReported, WorkerMessagingProxy()->TerminateGlobalScope();
WorkerMessagingProxy()->WaitForNotification());
EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity()); EXPECT_FALSE(WorkerMessagingProxy()->HasPendingActivity());
} }
......
...@@ -134,9 +134,6 @@ void InProcessWorkerMessagingProxy::PostMessageToWorkerGlobalScope( ...@@ -134,9 +134,6 @@ void InProcessWorkerMessagingProxy::PostMessageToWorkerGlobalScope(
return; return;
if (GetWorkerThread()) { if (GetWorkerThread()) {
// A message event is an activity and may initiate another activity.
worker_global_scope_has_pending_activity_ = true;
++unconfirmed_message_count_;
WTF::CrossThreadClosure task = CrossThreadBind( WTF::CrossThreadClosure task = CrossThreadBind(
&InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject, &InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject,
CrossThreadUnretained(&WorkerObjectProxy()), std::move(message), CrossThreadUnretained(&WorkerObjectProxy()), std::move(message),
...@@ -184,11 +181,6 @@ void InProcessWorkerMessagingProxy::WorkerThreadCreated() { ...@@ -184,11 +181,6 @@ void InProcessWorkerMessagingProxy::WorkerThreadCreated() {
DCHECK(IsParentContextThread()); DCHECK(IsParentContextThread());
ThreadedMessagingProxyBase::WorkerThreadCreated(); ThreadedMessagingProxyBase::WorkerThreadCreated();
// Worker initialization means a pending activity.
worker_global_scope_has_pending_activity_ = true;
DCHECK_EQ(0u, unconfirmed_message_count_);
unconfirmed_message_count_ = queued_early_tasks_.size();
for (auto& queued_task : queued_early_tasks_) { for (auto& queued_task : queued_early_tasks_) {
WTF::CrossThreadClosure task = CrossThreadBind( WTF::CrossThreadClosure task = CrossThreadBind(
&InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject, &InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject,
...@@ -202,26 +194,6 @@ void InProcessWorkerMessagingProxy::WorkerThreadCreated() { ...@@ -202,26 +194,6 @@ void InProcessWorkerMessagingProxy::WorkerThreadCreated() {
queued_early_tasks_.clear(); queued_early_tasks_.clear();
} }
void InProcessWorkerMessagingProxy::ConfirmMessageFromWorkerObject() {
DCHECK(IsParentContextThread());
if (AskedToTerminate())
return;
DCHECK(worker_global_scope_has_pending_activity_);
DCHECK_GT(unconfirmed_message_count_, 0u);
--unconfirmed_message_count_;
}
void InProcessWorkerMessagingProxy::PendingActivityFinished() {
DCHECK(IsParentContextThread());
DCHECK(worker_global_scope_has_pending_activity_);
if (unconfirmed_message_count_ > 0) {
// Ignore the report because an inflight message event may initiate a
// new activity.
return;
}
worker_global_scope_has_pending_activity_ = false;
}
DEFINE_TRACE(InProcessWorkerMessagingProxy) { DEFINE_TRACE(InProcessWorkerMessagingProxy) {
visitor->Trace(worker_object_); visitor->Trace(worker_object_);
ThreadedMessagingProxyBase::Trace(visitor); ThreadedMessagingProxyBase::Trace(visitor);
...@@ -229,9 +201,7 @@ DEFINE_TRACE(InProcessWorkerMessagingProxy) { ...@@ -229,9 +201,7 @@ DEFINE_TRACE(InProcessWorkerMessagingProxy) {
bool InProcessWorkerMessagingProxy::HasPendingActivity() const { bool InProcessWorkerMessagingProxy::HasPendingActivity() const {
DCHECK(IsParentContextThread()); DCHECK(IsParentContextThread());
if (AskedToTerminate()) return !AskedToTerminate();
return false;
return worker_global_scope_has_pending_activity_;
} }
} // namespace blink } // namespace blink
...@@ -72,13 +72,6 @@ class CORE_EXPORT InProcessWorkerMessagingProxy ...@@ -72,13 +72,6 @@ class CORE_EXPORT InProcessWorkerMessagingProxy
std::unique_ptr<SourceLocation>, std::unique_ptr<SourceLocation>,
int exception_id); int exception_id);
// 'virtual' for testing.
virtual void ConfirmMessageFromWorkerObject();
// Called from InProcessWorkerObjectProxy when all pending activities on the
// worker context are finished. See InProcessWorkerObjectProxy.h for details.
virtual void PendingActivityFinished();
DECLARE_VIRTUAL_TRACE(); DECLARE_VIRTUAL_TRACE();
protected: protected:
...@@ -116,15 +109,6 @@ class CORE_EXPORT InProcessWorkerMessagingProxy ...@@ -116,15 +109,6 @@ class CORE_EXPORT InProcessWorkerMessagingProxy
// Tasks are queued here until there's a thread object created. // Tasks are queued here until there's a thread object created.
struct QueuedTask; struct QueuedTask;
Vector<QueuedTask> queued_early_tasks_; Vector<QueuedTask> queued_early_tasks_;
// Unconfirmed messages from the parent context thread to the worker thread.
// When this is greater than 0, |m_workerGlobalScopeHasPendingActivity| should
// be true.
unsigned unconfirmed_message_count_ = 0;
// Indicates whether there are pending activities (e.g, MessageEvent,
// setTimeout) on the worker context.
bool worker_global_scope_has_pending_activity_ = false;
}; };
} // namespace blink } // namespace blink
......
...@@ -32,7 +32,6 @@ ...@@ -32,7 +32,6 @@
#include <memory> #include <memory>
#include "bindings/core/v8/SourceLocation.h" #include "bindings/core/v8/SourceLocation.h"
#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/serialization/SerializedScriptValue.h" #include "bindings/core/v8/serialization/SerializedScriptValue.h"
#include "core/dom/Document.h" #include "core/dom/Document.h"
#include "core/dom/ExecutionContext.h" #include "core/dom/ExecutionContext.h"
...@@ -51,9 +50,6 @@ ...@@ -51,9 +50,6 @@
namespace blink { namespace blink {
const double kDefaultIntervalInSec = 1;
const double kMaxIntervalInSec = 30;
std::unique_ptr<InProcessWorkerObjectProxy> InProcessWorkerObjectProxy::Create( std::unique_ptr<InProcessWorkerObjectProxy> InProcessWorkerObjectProxy::Create(
InProcessWorkerMessagingProxy* messaging_proxy_weak_ptr, InProcessWorkerMessagingProxy* messaging_proxy_weak_ptr,
ParentFrameTaskRunners* parent_frame_task_runners) { ParentFrameTaskRunners* parent_frame_task_runners) {
...@@ -85,16 +81,6 @@ void InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject( ...@@ -85,16 +81,6 @@ void InProcessWorkerObjectProxy::ProcessMessageFromWorkerObject(
MessagePortArray* ports = MessagePortArray* ports =
MessagePort::EntanglePorts(*global_scope, std::move(channels)); MessagePort::EntanglePorts(*global_scope, std::move(channels));
global_scope->DispatchEvent(MessageEvent::Create(ports, std::move(message))); global_scope->DispatchEvent(MessageEvent::Create(ports, std::move(message)));
GetParentFrameTaskRunners()
->Get(TaskType::kUnspecedTimer)
->PostTask(
BLINK_FROM_HERE,
CrossThreadBind(
&InProcessWorkerMessagingProxy::ConfirmMessageFromWorkerObject,
messaging_proxy_weak_ptr_));
StartPendingActivityTimer();
} }
void InProcessWorkerObjectProxy::ProcessUnhandledException( void InProcessWorkerObjectProxy::ProcessUnhandledException(
...@@ -122,21 +108,9 @@ void InProcessWorkerObjectProxy::DidCreateWorkerGlobalScope( ...@@ -122,21 +108,9 @@ void InProcessWorkerObjectProxy::DidCreateWorkerGlobalScope(
WorkerOrWorkletGlobalScope* global_scope) { WorkerOrWorkletGlobalScope* global_scope) {
DCHECK(!worker_global_scope_); DCHECK(!worker_global_scope_);
worker_global_scope_ = ToWorkerGlobalScope(global_scope); worker_global_scope_ = ToWorkerGlobalScope(global_scope);
// This timer task should be unthrottled in order to prevent GC timing from
// being delayed.
// TODO(nhiroki): Consider making a special task type for GC.
// (https://crbug.com/712504)
timer_ = WTF::MakeUnique<TaskRunnerTimer<InProcessWorkerObjectProxy>>(
TaskRunnerHelper::Get(TaskType::kUnthrottled, global_scope), this,
&InProcessWorkerObjectProxy::CheckPendingActivity);
}
void InProcessWorkerObjectProxy::DidEvaluateWorkerScript(bool) {
StartPendingActivityTimer();
} }
void InProcessWorkerObjectProxy::WillDestroyWorkerGlobalScope() { void InProcessWorkerObjectProxy::WillDestroyWorkerGlobalScope() {
timer_.reset();
worker_global_scope_ = nullptr; worker_global_scope_ = nullptr;
} }
...@@ -144,45 +118,7 @@ InProcessWorkerObjectProxy::InProcessWorkerObjectProxy( ...@@ -144,45 +118,7 @@ InProcessWorkerObjectProxy::InProcessWorkerObjectProxy(
InProcessWorkerMessagingProxy* messaging_proxy_weak_ptr, InProcessWorkerMessagingProxy* messaging_proxy_weak_ptr,
ParentFrameTaskRunners* parent_frame_task_runners) ParentFrameTaskRunners* parent_frame_task_runners)
: ThreadedObjectProxyBase(parent_frame_task_runners), : ThreadedObjectProxyBase(parent_frame_task_runners),
messaging_proxy_weak_ptr_(messaging_proxy_weak_ptr), messaging_proxy_weak_ptr_(messaging_proxy_weak_ptr) {}
default_interval_in_sec_(kDefaultIntervalInSec),
next_interval_in_sec_(kDefaultIntervalInSec),
max_interval_in_sec_(kMaxIntervalInSec) {}
void InProcessWorkerObjectProxy::StartPendingActivityTimer() {
if (timer_->IsActive()) {
// Reset the next interval duration to check new activity state timely.
// For example, a long-running activity can be cancelled by a message
// event.
next_interval_in_sec_ = kDefaultIntervalInSec;
return;
}
timer_->StartOneShot(next_interval_in_sec_, BLINK_FROM_HERE);
next_interval_in_sec_ =
std::min(next_interval_in_sec_ * 1.5, max_interval_in_sec_);
}
void InProcessWorkerObjectProxy::CheckPendingActivity(TimerBase*) {
bool has_pending_activity = V8GCController::HasPendingActivity(
worker_global_scope_->GetThread()->GetIsolate(), worker_global_scope_);
if (!has_pending_activity) {
// Report all activities are done.
GetParentFrameTaskRunners()
->Get(TaskType::kUnspecedTimer)
->PostTask(BLINK_FROM_HERE,
CrossThreadBind(
&InProcessWorkerMessagingProxy::PendingActivityFinished,
messaging_proxy_weak_ptr_));
// Don't schedule a timer. It will be started again when a message event
// is dispatched.
next_interval_in_sec_ = default_interval_in_sec_;
return;
}
// There is still a pending activity. Check it later.
StartPendingActivityTimer();
}
CrossThreadWeakPersistent<ThreadedMessagingProxyBase> CrossThreadWeakPersistent<ThreadedMessagingProxyBase>
InProcessWorkerObjectProxy::MessagingProxyWeakPtr() { InProcessWorkerObjectProxy::MessagingProxyWeakPtr() {
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "core/dom/MessagePort.h" #include "core/dom/MessagePort.h"
#include "core/workers/ThreadedObjectProxyBase.h" #include "core/workers/ThreadedObjectProxyBase.h"
#include "core/workers/WorkerReportingProxy.h" #include "core/workers/WorkerReportingProxy.h"
#include "platform/Timer.h"
#include "platform/heap/Handle.h" #include "platform/heap/Handle.h"
#include "platform/wtf/RefPtr.h" #include "platform/wtf/RefPtr.h"
#include "platform/wtf/WeakPtr.h" #include "platform/wtf/WeakPtr.h"
...@@ -77,7 +76,6 @@ class CORE_EXPORT InProcessWorkerObjectProxy : public ThreadedObjectProxyBase { ...@@ -77,7 +76,6 @@ class CORE_EXPORT InProcessWorkerObjectProxy : public ThreadedObjectProxyBase {
std::unique_ptr<SourceLocation>, std::unique_ptr<SourceLocation>,
int exception_id) override; int exception_id) override;
void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override; void DidCreateWorkerGlobalScope(WorkerOrWorkletGlobalScope*) override;
void DidEvaluateWorkerScript(bool success) override;
void WillDestroyWorkerGlobalScope() override; void WillDestroyWorkerGlobalScope() override;
protected: protected:
...@@ -90,32 +88,12 @@ class CORE_EXPORT InProcessWorkerObjectProxy : public ThreadedObjectProxyBase { ...@@ -90,32 +88,12 @@ class CORE_EXPORT InProcessWorkerObjectProxy : public ThreadedObjectProxyBase {
private: private:
friend class InProcessWorkerObjectProxyForTest; friend class InProcessWorkerObjectProxyForTest;
void StartPendingActivityTimer();
void CheckPendingActivity(TimerBase*);
// No guarantees about the lifetimes of tasks posted by this proxy wrt the // No guarantees about the lifetimes of tasks posted by this proxy wrt the
// InProcessWorkerMessagingProxy so a weak pointer must be used when posting // InProcessWorkerMessagingProxy so a weak pointer must be used when posting
// the tasks. // the tasks.
CrossThreadWeakPersistent<InProcessWorkerMessagingProxy> CrossThreadWeakPersistent<InProcessWorkerMessagingProxy>
messaging_proxy_weak_ptr_; messaging_proxy_weak_ptr_;
// Used for checking pending activities on the worker global scope. This is
// cancelled when the worker global scope is destroyed.
std::unique_ptr<TaskRunnerTimer<InProcessWorkerObjectProxy>> timer_;
// The default interval duration of the timer. This is usually
// kDefaultIntervalInSec but made as a member variable for testing.
double default_interval_in_sec_;
// The next interval duration of the timer. This is initially set to
// |m_defaultIntervalInSec| and exponentially increased up to
// |m_maxIntervalInSec|.
double next_interval_in_sec_;
// The max interval duration of the timer. This is usually kMaxIntervalInSec
// but made as a member variable for testing.
double max_interval_in_sec_;
CrossThreadPersistent<WorkerGlobalScope> worker_global_scope_; CrossThreadPersistent<WorkerGlobalScope> worker_global_scope_;
}; };
......
...@@ -249,7 +249,9 @@ v8::Local<v8::Object> WorkerGlobalScope::AssociateWithWrapper( ...@@ -249,7 +249,9 @@ v8::Local<v8::Object> WorkerGlobalScope::AssociateWithWrapper(
} }
bool WorkerGlobalScope::HasPendingActivity() const { bool WorkerGlobalScope::HasPendingActivity() const {
return timers_.HasInstalledTimeout(); // The worker global scope wrapper is kept alive as long as its execution
// context is alive.
return !ExecutionContext::IsContextDestroyed();
} }
bool WorkerGlobalScope::IsContextThread() const { bool WorkerGlobalScope::IsContextThread() const {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment