Commit 45a12805 authored by Hiroki Nakagawa's avatar Hiroki Nakagawa Committed by Commit Bot

Worker: Use lock annotations in WorkerThread

Lock annotations mechanism was ported from Abseil in this CL:
https://chromium-review.googlesource.com/c/chromium/src/+/885506

This mechanism provides Clang's built-in support for static lock analysis. This
would be really useful for workers, especially WorkerThread.

Bug: 812222
Change-Id: I88d4e24ea8a2d93edf126d61148d4c7aec060901
Reviewed-on: https://chromium-review.googlesource.com/919321Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Commit-Queue: Hiroki Nakagawa <nhiroki@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537294}
parent 03c55b23
...@@ -151,7 +151,7 @@ void WorkerThread::Terminate() { ...@@ -151,7 +151,7 @@ void WorkerThread::Terminate() {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
{ {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
if (requested_to_terminate_) if (requested_to_terminate_)
return; return;
requested_to_terminate_ = true; requested_to_terminate_ = true;
...@@ -241,13 +241,13 @@ ThreadableLoadingContext* WorkerThread::GetLoadingContext() { ...@@ -241,13 +241,13 @@ ThreadableLoadingContext* WorkerThread::GetLoadingContext() {
void WorkerThread::AppendDebuggerTask(CrossThreadClosure task) { void WorkerThread::AppendDebuggerTask(CrossThreadClosure task) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
if (requested_to_terminate_) if (CheckRequestedToTerminate())
return; return;
inspector_task_runner_->AppendTask(CrossThreadBind( inspector_task_runner_->AppendTask(CrossThreadBind(
&WorkerThread::PerformDebuggerTaskOnWorkerThread, &WorkerThread::PerformDebuggerTaskOnWorkerThread,
CrossThreadUnretained(this), WTF::Passed(std::move(task)))); CrossThreadUnretained(this), WTF::Passed(std::move(task))));
{ {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
if (GetIsolate() && thread_state_ != ThreadState::kReadyToShutdown) if (GetIsolate() && thread_state_ != ThreadState::kReadyToShutdown)
inspector_task_runner_->InterruptAndRunAllTasksDontWait(GetIsolate()); inspector_task_runner_->InterruptAndRunAllTasksDontWait(GetIsolate());
} }
...@@ -305,7 +305,7 @@ PlatformThreadId WorkerThread::GetPlatformThreadId() { ...@@ -305,7 +305,7 @@ PlatformThreadId WorkerThread::GetPlatformThreadId() {
} }
bool WorkerThread::IsForciblyTerminated() { bool WorkerThread::IsForciblyTerminated() {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
switch (exit_code_) { switch (exit_code_) {
case ExitCode::kNotTerminated: case ExitCode::kNotTerminated:
case ExitCode::kGracefullyTerminated: case ExitCode::kGracefullyTerminated:
...@@ -322,7 +322,7 @@ bool WorkerThread::IsForciblyTerminated() { ...@@ -322,7 +322,7 @@ bool WorkerThread::IsForciblyTerminated() {
} }
ExitCode WorkerThread::GetExitCodeForTesting() { ExitCode WorkerThread::GetExitCodeForTesting() {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
return exit_code_; return exit_code_;
} }
...@@ -353,10 +353,8 @@ void WorkerThread::ScheduleToTerminateScriptExecution() { ...@@ -353,10 +353,8 @@ void WorkerThread::ScheduleToTerminateScriptExecution() {
forcible_termination_delay_); forcible_termination_delay_);
} }
bool WorkerThread::ShouldTerminateScriptExecution(const MutexLocker& lock) { bool WorkerThread::ShouldTerminateScriptExecution() {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
DCHECK(IsThreadStateMutexLocked(lock));
switch (thread_state_) { switch (thread_state_) {
case ThreadState::kNotStarted: case ThreadState::kNotStarted:
// Shutdown sequence will surely start during initialization sequence // Shutdown sequence will surely start during initialization sequence
...@@ -378,13 +376,13 @@ bool WorkerThread::ShouldTerminateScriptExecution(const MutexLocker& lock) { ...@@ -378,13 +376,13 @@ bool WorkerThread::ShouldTerminateScriptExecution(const MutexLocker& lock) {
void WorkerThread::EnsureScriptExecutionTerminates(ExitCode exit_code) { void WorkerThread::EnsureScriptExecutionTerminates(ExitCode exit_code) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
if (!ShouldTerminateScriptExecution(lock)) if (!ShouldTerminateScriptExecution())
return; return;
DCHECK(exit_code == ExitCode::kSyncForciblyTerminated || DCHECK(exit_code == ExitCode::kSyncForciblyTerminated ||
exit_code == ExitCode::kAsyncForciblyTerminated); exit_code == ExitCode::kAsyncForciblyTerminated);
SetExitCode(lock, exit_code); SetExitCode(exit_code);
GetIsolate()->TerminateExecution(); GetIsolate()->TerminateExecution();
forcible_termination_task_handle_.Cancel(); forcible_termination_task_handle_.Cancel();
...@@ -409,12 +407,9 @@ void WorkerThread::InitializeOnWorkerThread( ...@@ -409,12 +407,9 @@ void WorkerThread::InitializeOnWorkerThread(
const WTF::Optional<WorkerBackingThreadStartupData>& thread_startup_data, const WTF::Optional<WorkerBackingThreadStartupData>& thread_startup_data,
WorkerInspectorProxy::PauseOnWorkerStart pause_on_start) { WorkerInspectorProxy::PauseOnWorkerStart pause_on_start) {
DCHECK(IsCurrentThread()); DCHECK(IsCurrentThread());
DCHECK_EQ(ThreadState::kNotStarted, thread_state_);
KURL script_url = global_scope_creation_params->script_url;
{ {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
DCHECK_EQ(ThreadState::kNotStarted, thread_state_);
if (IsOwningBackingThread()) { if (IsOwningBackingThread()) {
DCHECK(thread_startup_data.has_value()); DCHECK(thread_startup_data.has_value());
...@@ -440,13 +435,13 @@ void WorkerThread::InitializeOnWorkerThread( ...@@ -440,13 +435,13 @@ void WorkerThread::InitializeOnWorkerThread(
GlobalScope()->ScriptController()->GetContext()); GlobalScope()->ScriptController()->GetContext());
} }
SetThreadState(lock, ThreadState::kRunning); SetThreadState(ThreadState::kRunning);
} }
if (pause_on_start == WorkerInspectorProxy::PauseOnWorkerStart::kPause) if (pause_on_start == WorkerInspectorProxy::PauseOnWorkerStart::kPause)
StartRunningDebuggerTasksOnPauseOnWorkerThread(); StartRunningDebuggerTasksOnPauseOnWorkerThread();
if (CheckRequestedToTerminateOnWorkerThread()) { if (CheckRequestedToTerminate()) {
// Stop further worker tasks from running after this point. WorkerThread // Stop further worker tasks from running after this point. WorkerThread
// was requested to terminate before initialization or during running // was requested to terminate before initialization or during running
// debugger tasks. PerformShutdownOnWorkerThread() will be called soon. // debugger tasks. PerformShutdownOnWorkerThread() will be called soon.
...@@ -481,12 +476,12 @@ void WorkerThread::ImportModuleScriptOnWorkerThread( ...@@ -481,12 +476,12 @@ void WorkerThread::ImportModuleScriptOnWorkerThread(
void WorkerThread::PrepareForShutdownOnWorkerThread() { void WorkerThread::PrepareForShutdownOnWorkerThread() {
DCHECK(IsCurrentThread()); DCHECK(IsCurrentThread());
{ {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
if (thread_state_ == ThreadState::kReadyToShutdown) if (thread_state_ == ThreadState::kReadyToShutdown)
return; return;
SetThreadState(lock, ThreadState::kReadyToShutdown); SetThreadState(ThreadState::kReadyToShutdown);
if (exit_code_ == ExitCode::kNotTerminated) if (exit_code_ == ExitCode::kNotTerminated)
SetExitCode(lock, ExitCode::kGracefullyTerminated); SetExitCode(ExitCode::kGracefullyTerminated);
} }
inspector_task_runner_->Kill(); inspector_task_runner_->Kill();
...@@ -509,8 +504,13 @@ void WorkerThread::PrepareForShutdownOnWorkerThread() { ...@@ -509,8 +504,13 @@ void WorkerThread::PrepareForShutdownOnWorkerThread() {
void WorkerThread::PerformShutdownOnWorkerThread() { void WorkerThread::PerformShutdownOnWorkerThread() {
DCHECK(IsCurrentThread()); DCHECK(IsCurrentThread());
DCHECK(CheckRequestedToTerminateOnWorkerThread()); #if DCHECK_IS_ON()
DCHECK_EQ(ThreadState::kReadyToShutdown, thread_state_); {
MutexLocker lock(mutex_);
DCHECK(requested_to_terminate_);
DCHECK_EQ(ThreadState::kReadyToShutdown, thread_state_);
}
#endif
if (IsOwningBackingThread()) if (IsOwningBackingThread())
GetWorkerBackingThread().ShutdownOnBackingThread(); GetWorkerBackingThread().ShutdownOnBackingThread();
...@@ -529,7 +529,7 @@ void WorkerThread::PerformDebuggerTaskOnWorkerThread(CrossThreadClosure task) { ...@@ -529,7 +529,7 @@ void WorkerThread::PerformDebuggerTaskOnWorkerThread(CrossThreadClosure task) {
InspectorTaskRunner::IgnoreInterruptsScope scope( InspectorTaskRunner::IgnoreInterruptsScope scope(
inspector_task_runner_.get()); inspector_task_runner_.get());
{ {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
DCHECK_EQ(ThreadState::kRunning, thread_state_); DCHECK_EQ(ThreadState::kRunning, thread_state_);
running_debugger_task_ = true; running_debugger_task_ = true;
} }
...@@ -537,7 +537,7 @@ void WorkerThread::PerformDebuggerTaskOnWorkerThread(CrossThreadClosure task) { ...@@ -537,7 +537,7 @@ void WorkerThread::PerformDebuggerTaskOnWorkerThread(CrossThreadClosure task) {
std::move(task).Run(); std::move(task).Run();
ThreadDebugger::IdleStarted(GetIsolate()); ThreadDebugger::IdleStarted(GetIsolate());
{ {
MutexLocker lock(thread_state_mutex_); MutexLocker lock(mutex_);
running_debugger_task_ = false; running_debugger_task_ = false;
} }
} }
...@@ -550,9 +550,7 @@ void WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread() { ...@@ -550,9 +550,7 @@ void WorkerThread::PerformDebuggerTaskDontWaitOnWorkerThread() {
std::move(task).Run(); std::move(task).Run();
} }
void WorkerThread::SetThreadState(const MutexLocker& lock, void WorkerThread::SetThreadState(ThreadState next_thread_state) {
ThreadState next_thread_state) {
DCHECK(IsThreadStateMutexLocked(lock));
switch (next_thread_state) { switch (next_thread_state) {
case ThreadState::kNotStarted: case ThreadState::kNotStarted:
NOTREACHED(); NOTREACHED();
...@@ -568,24 +566,13 @@ void WorkerThread::SetThreadState(const MutexLocker& lock, ...@@ -568,24 +566,13 @@ void WorkerThread::SetThreadState(const MutexLocker& lock,
} }
} }
void WorkerThread::SetExitCode(const MutexLocker& lock, ExitCode exit_code) { void WorkerThread::SetExitCode(ExitCode exit_code) {
DCHECK(IsThreadStateMutexLocked(lock));
DCHECK_EQ(ExitCode::kNotTerminated, exit_code_); DCHECK_EQ(ExitCode::kNotTerminated, exit_code_);
exit_code_ = exit_code; exit_code_ = exit_code;
} }
bool WorkerThread::IsThreadStateMutexLocked(const MutexLocker& /* unused */) { bool WorkerThread::CheckRequestedToTerminate() {
#if DCHECK_IS_ON() MutexLocker lock(mutex_);
// Mutex::locked() is available only if DCHECK_IS_ON() is true.
return thread_state_mutex_.Locked();
#else
// Otherwise, believe the given MutexLocker holds |m_threadStateMutex|.
return true;
#endif
}
bool WorkerThread::CheckRequestedToTerminateOnWorkerThread() {
MutexLocker lock(thread_state_mutex_);
return requested_to_terminate_; return requested_to_terminate_;
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/thread_annotations.h"
#include "base/unguessable_token.h" #include "base/unguessable_token.h"
#include "core/CoreExport.h" #include "core/CoreExport.h"
#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/frame/csp/ContentSecurityPolicy.h"
...@@ -118,7 +119,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -118,7 +119,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
// the underlying thread. This task may be blocked by JavaScript execution on // the underlying thread. This task may be blocked by JavaScript execution on
// the worker thread, so this function also forcibly terminates JavaScript // the worker thread, so this function also forcibly terminates JavaScript
// execution after a certain grace period. // execution after a certain grace period.
void Terminate(); void Terminate() LOCKS_EXCLUDED(mutex_);
// Terminates the worker thread. Subclasses of WorkerThread can override this // Terminates the worker thread. Subclasses of WorkerThread can override this
// to do cleanup. The default behavior is to call Terminate() and // to do cleanup. The default behavior is to call Terminate() and
...@@ -154,7 +155,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -154,7 +155,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
} }
// Only callable on the main thread. // Only callable on the main thread.
void AppendDebuggerTask(CrossThreadClosure); void AppendDebuggerTask(CrossThreadClosure) LOCKS_EXCLUDED(mutex_);
// Only callable on the main thread. // Only callable on the main thread.
const base::UnguessableToken& GetDevToolsWorkerToken() const { const base::UnguessableToken& GetDevToolsWorkerToken() const {
...@@ -187,10 +188,10 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -187,10 +188,10 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
PlatformThreadId GetPlatformThreadId(); PlatformThreadId GetPlatformThreadId();
bool IsForciblyTerminated(); bool IsForciblyTerminated() LOCKS_EXCLUDED(mutex_);
void WaitForShutdownForTesting() { shutdown_event_->Wait(); } void WaitForShutdownForTesting() { shutdown_event_->Wait(); }
ExitCode GetExitCodeForTesting(); ExitCode GetExitCodeForTesting() LOCKS_EXCLUDED(mutex_);
ParentFrameTaskRunners* GetParentFrameTaskRunners() const { ParentFrameTaskRunners* GetParentFrameTaskRunners() const {
return parent_frame_task_runners_.Get(); return parent_frame_task_runners_.Get();
...@@ -224,11 +225,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -224,11 +225,7 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
FRIEND_TEST_ALL_PREFIXES(WorkerThreadTest, FRIEND_TEST_ALL_PREFIXES(WorkerThreadTest,
Terminate_WhileDebuggerTaskIsRunning); Terminate_WhileDebuggerTaskIsRunning);
// Represents the state of this worker thread. A caller may need to acquire // Represents the state of this worker thread.
// a lock |m_threadStateMutex| before accessing this:
// - Only the worker thread can set this with the lock.
// - The worker thread can read this without the lock.
// - The main thread can read this with the lock.
enum class ThreadState { enum class ThreadState {
kNotStarted, kNotStarted,
kRunning, kRunning,
...@@ -252,23 +249,22 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -252,23 +249,22 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
void ScheduleToTerminateScriptExecution(); void ScheduleToTerminateScriptExecution();
// Returns true if we should synchronously terminate the script execution so // Returns true if we should synchronously terminate the script execution so
// that a shutdown task can be handled by the thread event loop. This must be // that a shutdown task can be handled by the thread event loop.
// called with |m_threadStateMutex| acquired. bool ShouldTerminateScriptExecution() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool ShouldTerminateScriptExecution(const MutexLocker&);
// Terminates worker script execution if the worker thread is running and not // Terminates worker script execution if the worker thread is running and not
// already shutting down. Does not terminate if a debugger task is running, // already shutting down. Does not terminate if a debugger task is running,
// because the debugger task is guaranteed to finish and it heavily uses V8 // because the debugger task is guaranteed to finish and it heavily uses V8
// API calls which would crash after forcible script termination. Called on // API calls which would crash after forcible script termination. Called on
// the main thread. // the main thread.
void EnsureScriptExecutionTerminates(ExitCode); void EnsureScriptExecutionTerminates(ExitCode) LOCKS_EXCLUDED(mutex_);
// These are called in this order during worker thread startup. // These are called in this order during worker thread startup.
void InitializeSchedulerOnWorkerThread(WaitableEvent*); void InitializeSchedulerOnWorkerThread(WaitableEvent*);
void InitializeOnWorkerThread( void InitializeOnWorkerThread(
std::unique_ptr<GlobalScopeCreationParams>, std::unique_ptr<GlobalScopeCreationParams>,
const WTF::Optional<WorkerBackingThreadStartupData>&, const WTF::Optional<WorkerBackingThreadStartupData>&,
WorkerInspectorProxy::PauseOnWorkerStart); WorkerInspectorProxy::PauseOnWorkerStart) LOCKS_EXCLUDED(mutex_);
void EvaluateClassicScriptOnWorkerThread( void EvaluateClassicScriptOnWorkerThread(
const KURL& script_url, const KURL& script_url,
...@@ -279,36 +275,32 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -279,36 +275,32 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
network::mojom::FetchCredentialsMode); network::mojom::FetchCredentialsMode);
// These are called in this order during worker thread termination. // These are called in this order during worker thread termination.
void PrepareForShutdownOnWorkerThread(); void PrepareForShutdownOnWorkerThread() LOCKS_EXCLUDED(mutex_);
void PerformShutdownOnWorkerThread(); void PerformShutdownOnWorkerThread() LOCKS_EXCLUDED(mutex_);
void PerformDebuggerTaskOnWorkerThread(CrossThreadClosure); void PerformDebuggerTaskOnWorkerThread(CrossThreadClosure)
LOCKS_EXCLUDED(mutex_);
void PerformDebuggerTaskDontWaitOnWorkerThread(); void PerformDebuggerTaskDontWaitOnWorkerThread();
// These must be called with |m_threadStateMutex| acquired. void SetThreadState(ThreadState) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void SetThreadState(const MutexLocker&, ThreadState); void SetExitCode(ExitCode) EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void SetExitCode(const MutexLocker&, ExitCode);
bool IsThreadStateMutexLocked(const MutexLocker&);
// This internally acquires |m_threadStateMutex|. If you already have the bool CheckRequestedToTerminate() LOCKS_EXCLUDED(mutex_);
// lock or you're on the main thread, you should consider directly accessing
// |m_requestedToTerminate|.
bool CheckRequestedToTerminateOnWorkerThread();
// A unique identifier among all WorkerThreads. // A unique identifier among all WorkerThreads.
const int worker_thread_id_; const int worker_thread_id_;
// Set on the main thread and checked on both the main and worker threads. // Set on the main thread.
bool requested_to_terminate_ = false; bool requested_to_terminate_ GUARDED_BY(mutex_) = false;
// Accessed only on the worker thread. // Accessed only on the worker thread.
bool paused_in_debugger_ = false; bool paused_in_debugger_ = false;
// Set on the worker thread and checked on both the main and worker threads. // Set on the worker thread.
bool running_debugger_task_ = false; bool running_debugger_task_ GUARDED_BY(mutex_) = false;
ThreadState thread_state_ = ThreadState::kNotStarted; ThreadState thread_state_ GUARDED_BY(mutex_) = ThreadState::kNotStarted;
ExitCode exit_code_ = ExitCode::kNotTerminated; ExitCode exit_code_ GUARDED_BY(mutex_) = ExitCode::kNotTerminated;
TimeDelta forcible_termination_delay_; TimeDelta forcible_termination_delay_;
...@@ -328,9 +320,10 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver { ...@@ -328,9 +320,10 @@ class CORE_EXPORT WorkerThread : public WebThread::TaskObserver {
std::unique_ptr<scheduler::WorkerGlobalScopeScheduler> std::unique_ptr<scheduler::WorkerGlobalScopeScheduler>
global_scope_scheduler_; global_scope_scheduler_;
// This lock protects |m_globalScope|, |m_requestedToTerminate|, // This lock protects shared states between the main thread and the worker
// |m_threadState|, |m_runningDebuggerTask| and |m_exitCode|. // thread. See thread-safety annotations (e.g., GUARDED_BY) in this header
Mutex thread_state_mutex_; // file.
Mutex mutex_;
CrossThreadPersistent<ConsoleMessageStorage> console_message_storage_; CrossThreadPersistent<ConsoleMessageStorage> console_message_storage_;
CrossThreadPersistent<WorkerOrWorkletGlobalScope> global_scope_; CrossThreadPersistent<WorkerOrWorkletGlobalScope> global_scope_;
......
...@@ -146,23 +146,25 @@ class WorkerThreadTest : public ::testing::Test { ...@@ -146,23 +146,25 @@ class WorkerThreadTest : public ::testing::Test {
TEST_F(WorkerThreadTest, ShouldTerminateScriptExecution) { TEST_F(WorkerThreadTest, ShouldTerminateScriptExecution) {
using ThreadState = WorkerThread::ThreadState; using ThreadState = WorkerThread::ThreadState;
MutexLocker dummy_lock(worker_thread_->thread_state_mutex_);
// SetExitCode() and ShouldTerminateScriptExecution() require the lock.
MutexLocker dummy_lock(worker_thread_->mutex_);
EXPECT_EQ(ThreadState::kNotStarted, worker_thread_->thread_state_); EXPECT_EQ(ThreadState::kNotStarted, worker_thread_->thread_state_);
EXPECT_FALSE(worker_thread_->ShouldTerminateScriptExecution(dummy_lock)); EXPECT_FALSE(worker_thread_->ShouldTerminateScriptExecution());
worker_thread_->SetThreadState(dummy_lock, ThreadState::kRunning); worker_thread_->SetThreadState(ThreadState::kRunning);
EXPECT_FALSE(worker_thread_->running_debugger_task_); EXPECT_FALSE(worker_thread_->running_debugger_task_);
EXPECT_TRUE(worker_thread_->ShouldTerminateScriptExecution(dummy_lock)); EXPECT_TRUE(worker_thread_->ShouldTerminateScriptExecution());
worker_thread_->running_debugger_task_ = true; worker_thread_->running_debugger_task_ = true;
EXPECT_FALSE(worker_thread_->ShouldTerminateScriptExecution(dummy_lock)); EXPECT_FALSE(worker_thread_->ShouldTerminateScriptExecution());
worker_thread_->SetThreadState(dummy_lock, ThreadState::kReadyToShutdown); worker_thread_->SetThreadState(ThreadState::kReadyToShutdown);
EXPECT_FALSE(worker_thread_->ShouldTerminateScriptExecution(dummy_lock)); EXPECT_FALSE(worker_thread_->ShouldTerminateScriptExecution());
// This is necessary to satisfy DCHECK in the dtor of WorkerThread. // This is necessary to satisfy DCHECK in the dtor of WorkerThread.
worker_thread_->SetExitCode(dummy_lock, ExitCode::kGracefullyTerminated); worker_thread_->SetExitCode(ExitCode::kGracefullyTerminated);
} }
TEST_F(WorkerThreadTest, AsyncTerminate_OnIdle) { TEST_F(WorkerThreadTest, AsyncTerminate_OnIdle) {
......
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