• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/threading/hang_watcher.h"
6 
7 #include <atomic>
8 #include <memory>
9 #include <optional>
10 
11 #include "base/barrier_closure.h"
12 #include "base/functional/bind.h"
13 #include "base/functional/callback.h"
14 #include "base/functional/callback_helpers.h"
15 #include "base/memory/raw_ptr.h"
16 #include "base/metrics/field_trial_params.h"
17 #include "base/run_loop.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/synchronization/lock.h"
20 #include "base/synchronization/waitable_event.h"
21 #include "base/test/bind.h"
22 #include "base/test/metrics/histogram_tester.h"
23 #include "base/test/power_monitor_test.h"
24 #include "base/test/scoped_feature_list.h"
25 #include "base/test/simple_test_tick_clock.h"
26 #include "base/test/task_environment.h"
27 #include "base/test/test_timeouts.h"
28 #include "base/threading/platform_thread.h"
29 #include "base/threading/thread_checker.h"
30 #include "base/threading/threading_features.h"
31 #include "base/time/tick_clock.h"
32 #include "base/time/time.h"
33 #include "build/build_config.h"
34 #include "testing/gmock/include/gmock/gmock.h"
35 #include "testing/gtest/include/gtest/gtest.h"
36 
37 using testing::ElementsAre;
38 using testing::IsEmpty;
39 
40 namespace base {
41 namespace {
42 
43 // Use with a FeatureList to activate crash dumping for threads marked as
44 // threadpool threads.
45 const std::vector<base::test::FeatureRefAndParams> kFeatureAndParams{
46     {base::kEnableHangWatcher, {{"ui_thread_log_level", "2"}}}};
47 
48 // Use this value to mark things very far off in the future. Adding this
49 // to TimeTicks::Now() gives a point that will never be reached during the
50 // normal execution of a test.
51 constexpr TimeDelta kVeryLongDelta{base::Days(365)};
52 
53 // A relatively small time delta to ensure ordering of hung threads list.
54 constexpr TimeDelta kSmallCPUQuantum{base::Milliseconds(1)};
55 
56 constexpr uint64_t kArbitraryDeadline = 0x0000C0FFEEC0FFEEu;
57 constexpr uint64_t kAllOnes = 0xFFFFFFFFFFFFFFFFu;
58 constexpr uint64_t kAllZeros = 0x0000000000000000u;
59 constexpr uint64_t kOnesThenZeroes = 0xAAAAAAAAAAAAAAAAu;
60 constexpr uint64_t kZeroesThenOnes = 0x5555555555555555u;
61 
62 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
63 class HangWatcherEnabledInZygoteChildTest : public testing::Test {
64  public:
HangWatcherEnabledInZygoteChildTest()65   HangWatcherEnabledInZygoteChildTest() {
66     std::vector<base::test::FeatureRefAndParams> enabled_features =
67         kFeatureAndParams;
68     feature_list_.InitWithFeaturesAndParameters(enabled_features, {});
69     HangWatcher::InitializeOnMainThread(
70         HangWatcher::ProcessType::kUtilityProcess,
71         /*emit_crashes=*/true);
72   }
73 
TearDown()74   void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
75 
76   HangWatcherEnabledInZygoteChildTest(
77       const HangWatcherEnabledInZygoteChildTest& other) = delete;
78   HangWatcherEnabledInZygoteChildTest& operator=(
79       const HangWatcherEnabledInZygoteChildTest& other) = delete;
80 
81  protected:
82   base::test::ScopedFeatureList feature_list_;
83 };
84 
TEST_F(HangWatcherEnabledInZygoteChildTest,IsEnabled)85 TEST_F(HangWatcherEnabledInZygoteChildTest, IsEnabled) {
86   ASSERT_TRUE(HangWatcher::IsEnabled());
87 }
88 
89 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
90 
91 // Waits on provided WaitableEvent before executing and signals when done.
92 class BlockingThread : public DelegateSimpleThread::Delegate {
93  public:
BlockingThread(base::WaitableEvent * unblock_thread,base::TimeDelta timeout)94   explicit BlockingThread(base::WaitableEvent* unblock_thread,
95                           base::TimeDelta timeout)
96       : thread_(this, "BlockingThread"),
97         unblock_thread_(unblock_thread),
98         timeout_(timeout) {}
99 
100   ~BlockingThread() override = default;
101 
Run()102   void Run() override {
103     // (Un)Register the thread here instead of in ctor/dtor so that the action
104     // happens on the right thread.
105     base::ScopedClosureRunner unregister_closure =
106         base::HangWatcher::RegisterThread(
107             base::HangWatcher::ThreadType::kMainThread);
108 
109     WatchHangsInScope scope(timeout_);
110     wait_until_entered_scope_.Signal();
111 
112     unblock_thread_->Wait();
113     run_event_.Signal();
114   }
115 
IsDone()116   bool IsDone() { return run_event_.IsSignaled(); }
117 
StartAndWaitForScopeEntered()118   void StartAndWaitForScopeEntered() {
119     thread_.Start();
120     // Block until this thread registered itself for hang watching and has
121     // entered a WatchHangsInScope.
122     wait_until_entered_scope_.Wait();
123   }
124 
Join()125   void Join() { thread_.Join(); }
126 
GetId()127   PlatformThreadId GetId() { return thread_.tid(); }
128 
129  private:
130   base::DelegateSimpleThread thread_;
131 
132   // Will be signaled once the thread is properly registered for watching and
133   // the WatchHangsInScope has been entered.
134   WaitableEvent wait_until_entered_scope_;
135 
136   // Will be signaled once ThreadMain has run.
137   WaitableEvent run_event_;
138 
139   const raw_ptr<base::WaitableEvent> unblock_thread_;
140 
141   base::TimeDelta timeout_;
142 };
143 
144 class HangWatcherTest : public testing::Test {
145  public:
146   const base::TimeDelta kTimeout = base::Seconds(10);
147   const base::TimeDelta kHangTime = kTimeout + base::Seconds(1);
148 
HangWatcherTest()149   HangWatcherTest() {
150     feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
151     HangWatcher::InitializeOnMainThread(
152         HangWatcher::ProcessType::kBrowserProcess, /*emit_crashes=*/true);
153 
154     hang_watcher_.SetAfterMonitorClosureForTesting(base::BindRepeating(
155         &WaitableEvent::Signal, base::Unretained(&monitor_event_)));
156 
157     hang_watcher_.SetOnHangClosureForTesting(base::BindRepeating(
158         &WaitableEvent::Signal, base::Unretained(&hang_event_)));
159 
160     // We're not testing the monitoring loop behavior in this test so we want to
161     // trigger monitoring manually.
162     hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
163 
164     // Start the monitoring loop.
165     hang_watcher_.Start();
166   }
167 
TearDown()168   void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
169 
170   HangWatcherTest(const HangWatcherTest& other) = delete;
171   HangWatcherTest& operator=(const HangWatcherTest& other) = delete;
172 
173  protected:
174   // Used to wait for monitoring. Will be signaled by the HangWatcher thread and
175   // so needs to outlive it.
176   WaitableEvent monitor_event_;
177 
178   // Signaled from the HangWatcher thread when a hang is detected. Needs to
179   // outlive the HangWatcher thread.
180   WaitableEvent hang_event_;
181 
182   base::test::ScopedFeatureList feature_list_;
183 
184   // Used exclusively for MOCK_TIME. No tasks will be run on the environment.
185   // Single threaded to avoid ThreadPool WorkerThreads registering.
186   test::SingleThreadTaskEnvironment task_environment_{
187       test::TaskEnvironment::TimeSource::MOCK_TIME};
188 
189   // This must be declared last (after task_environment_, for example) so that
190   // the watcher thread is joined before objects like the mock timer are
191   // destroyed, causing racy crashes.
192   HangWatcher hang_watcher_;
193 };
194 
195 class HangWatcherBlockingThreadTest : public HangWatcherTest {
196  public:
HangWatcherBlockingThreadTest()197   HangWatcherBlockingThreadTest() : thread_(&unblock_thread_, kTimeout) {}
198 
199   HangWatcherBlockingThreadTest(const HangWatcherBlockingThreadTest& other) =
200       delete;
201   HangWatcherBlockingThreadTest& operator=(
202       const HangWatcherBlockingThreadTest& other) = delete;
203 
204  protected:
JoinThread()205   void JoinThread() {
206     unblock_thread_.Signal();
207 
208     // Thread is joinable since we signaled |unblock_thread_|.
209     thread_.Join();
210 
211     // If thread is done then it signaled.
212     ASSERT_TRUE(thread_.IsDone());
213   }
214 
StartBlockedThread()215   void StartBlockedThread() {
216     // Thread has not run yet.
217     ASSERT_FALSE(thread_.IsDone());
218 
219     // Start the thread. It will block since |unblock_thread_| was not
220     // signaled yet.
221     thread_.StartAndWaitForScopeEntered();
222 
223     // Thread registration triggered a call to HangWatcher::Monitor() which
224     // signaled |monitor_event_|. Reset it so it's ready for waiting later on.
225     monitor_event_.Reset();
226   }
227 
MonitorHangs()228   void MonitorHangs() {
229     // HangWatcher::Monitor() should not be set which would mean a call to
230     // HangWatcher::Monitor() happened and was unacounted for.
231     // ASSERT_FALSE(monitor_event_.IsSignaled());
232 
233     // Trigger a monitoring on HangWatcher thread and verify results.
234     hang_watcher_.SignalMonitorEventForTesting();
235     monitor_event_.Wait();
236   }
237 
238   // Used to unblock the monitored thread. Signaled from the test main thread.
239   WaitableEvent unblock_thread_;
240 
241   BlockingThread thread_;
242 };
243 }  // namespace
244 
TEST_F(HangWatcherTest,InvalidatingExpectationsPreventsCapture)245 TEST_F(HangWatcherTest, InvalidatingExpectationsPreventsCapture) {
246   // Register the main test thread for hang watching.
247   auto unregister_thread_closure =
248       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
249 
250   // Create a hang.
251   WatchHangsInScope expires_instantly(base::TimeDelta{});
252   task_environment_.FastForwardBy(kHangTime);
253 
254   // de-activate hang watching,
255   base::HangWatcher::InvalidateActiveExpectations();
256 
257   // Trigger a monitoring on HangWatcher thread and verify results.
258   // Hang is not detected.
259   hang_watcher_.SignalMonitorEventForTesting();
260   monitor_event_.Wait();
261   ASSERT_FALSE(hang_event_.IsSignaled());
262 }
263 
TEST_F(HangWatcherTest,MultipleInvalidateExpectationsDoNotCancelOut)264 TEST_F(HangWatcherTest, MultipleInvalidateExpectationsDoNotCancelOut) {
265   // Register the main test thread for hang watching.
266   auto unregister_thread_closure =
267       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
268 
269   // Create a hang.
270   WatchHangsInScope expires_instantly(base::TimeDelta{});
271   task_environment_.FastForwardBy(kHangTime);
272 
273   // de-activate hang watching,
274   base::HangWatcher::InvalidateActiveExpectations();
275 
276   // Redundently de-activate hang watching.
277   base::HangWatcher::InvalidateActiveExpectations();
278 
279   // Trigger a monitoring on HangWatcher thread and verify results.
280   // Hang is not detected.
281   hang_watcher_.SignalMonitorEventForTesting();
282   monitor_event_.Wait();
283   ASSERT_FALSE(hang_event_.IsSignaled());
284 }
285 
TEST_F(HangWatcherTest,NewInnerWatchHangsInScopeAfterInvalidationDetectsHang)286 TEST_F(HangWatcherTest, NewInnerWatchHangsInScopeAfterInvalidationDetectsHang) {
287   // Register the main test thread for hang watching.
288   auto unregister_thread_closure =
289       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
290 
291   WatchHangsInScope expires_instantly(base::TimeDelta{});
292   task_environment_.FastForwardBy(kHangTime);
293 
294   // De-activate hang watching.
295   base::HangWatcher::InvalidateActiveExpectations();
296 
297   {
298     WatchHangsInScope also_expires_instantly(base::TimeDelta{});
299     task_environment_.FastForwardBy(kHangTime);
300 
301     // Trigger a monitoring on HangWatcher thread and verify results.
302     hang_watcher_.SignalMonitorEventForTesting();
303     monitor_event_.Wait();
304 
305     // Hang is detected since the new WatchHangsInScope temporarily
306     // re-activated hang_watching.
307     monitor_event_.Wait();
308     ASSERT_TRUE(hang_event_.IsSignaled());
309   }
310 
311   // Reset to attempt capture again.
312   monitor_event_.Reset();
313   hang_event_.Reset();
314 
315   // Trigger a monitoring on HangWatcher thread and verify results.
316   hang_watcher_.SignalMonitorEventForTesting();
317   monitor_event_.Wait();
318 
319   // Hang is not detected since execution is back to being covered by
320   // |expires_instantly| for which expectations were invalidated.
321   monitor_event_.Wait();
322   ASSERT_FALSE(hang_event_.IsSignaled());
323 }
324 
TEST_F(HangWatcherTest,NewSeparateWatchHangsInScopeAfterInvalidationDetectsHang)325 TEST_F(HangWatcherTest,
326        NewSeparateWatchHangsInScopeAfterInvalidationDetectsHang) {
327   // Register the main test thread for hang watching.
328   auto unregister_thread_closure =
329       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
330 
331   {
332     WatchHangsInScope expires_instantly(base::TimeDelta{});
333     task_environment_.FastForwardBy(kHangTime);
334 
335     // De-activate hang watching.
336     base::HangWatcher::InvalidateActiveExpectations();
337   }
338 
339   WatchHangsInScope also_expires_instantly(base::TimeDelta{});
340   task_environment_.FastForwardBy(kHangTime);
341 
342   // Trigger a monitoring on HangWatcher thread and verify results.
343   hang_watcher_.SignalMonitorEventForTesting();
344   monitor_event_.Wait();
345 
346   // Hang is detected since the new WatchHangsInScope did not have its
347   // expectations invalidated.
348   monitor_event_.Wait();
349   ASSERT_TRUE(hang_event_.IsSignaled());
350 }
351 
352 // Test that invalidating expectations from inner WatchHangsInScope will also
353 // prevent hang detection in outer scopes.
TEST_F(HangWatcherTest,ScopeDisabledObjectInnerScope)354 TEST_F(HangWatcherTest, ScopeDisabledObjectInnerScope) {
355   // Register the main test thread for hang watching.
356   auto unregister_thread_closure =
357       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
358 
359   // Start a WatchHangsInScope that expires right away. Then advance
360   // time to make sure no hang is detected.
361   WatchHangsInScope expires_instantly(base::TimeDelta{});
362   task_environment_.FastForwardBy(kHangTime);
363   {
364     WatchHangsInScope also_expires_instantly(base::TimeDelta{});
365 
366     // De-activate hang watching.
367     base::HangWatcher::InvalidateActiveExpectations();
368     task_environment_.FastForwardBy(kHangTime);
369   }
370 
371   // Trigger a monitoring on HangWatcher thread and verify results.
372   hang_watcher_.SignalMonitorEventForTesting();
373   monitor_event_.Wait();
374 
375   // Hang is ignored since it concerns a scope for which one of the inner scope
376   // was ignored.
377   ASSERT_FALSE(hang_event_.IsSignaled());
378 }
379 
TEST_F(HangWatcherTest,NewScopeAfterDisabling)380 TEST_F(HangWatcherTest, NewScopeAfterDisabling) {
381   // Register the main test thread for hang watching.
382   auto unregister_thread_closure =
383       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
384 
385   // Start a WatchHangsInScope that expires right away. Then advance
386   // time to make sure no hang is detected.
387   WatchHangsInScope expires_instantly(base::TimeDelta{});
388   task_environment_.FastForwardBy(kHangTime);
389   {
390     WatchHangsInScope also_expires_instantly(base::TimeDelta{});
391 
392     // De-activate hang watching.
393     base::HangWatcher::InvalidateActiveExpectations();
394     task_environment_.FastForwardBy(kHangTime);
395   }
396 
397   // New scope for which expecations are never invalidated.
398   WatchHangsInScope also_expires_instantly(base::TimeDelta{});
399   task_environment_.FastForwardBy(kHangTime);
400 
401   // Trigger a monitoring on HangWatcher thread and verify results.
402   hang_watcher_.SignalMonitorEventForTesting();
403   monitor_event_.Wait();
404 
405   // Hang is detected because it's unrelated to the hangs that were disabled.
406   ASSERT_TRUE(hang_event_.IsSignaled());
407 }
408 
TEST_F(HangWatcherTest,NestedScopes)409 TEST_F(HangWatcherTest, NestedScopes) {
410   // Create a state object for the test thread since this test is single
411   // threaded.
412   auto current_hang_watch_state =
413       base::internal::HangWatchState::CreateHangWatchStateForCurrentThread(
414           HangWatcher::ThreadType::kMainThread);
415 
416   ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
417   base::TimeTicks original_deadline = current_hang_watch_state->GetDeadline();
418 
419   constexpr base::TimeDelta kFirstTimeout(base::Milliseconds(500));
420   base::TimeTicks first_deadline = base::TimeTicks::Now() + kFirstTimeout;
421 
422   constexpr base::TimeDelta kSecondTimeout(base::Milliseconds(250));
423   base::TimeTicks second_deadline = base::TimeTicks::Now() + kSecondTimeout;
424 
425   // At this point we have not set any timeouts.
426   {
427     // Create a first timeout which is more restrictive than the default.
428     WatchHangsInScope first_scope(kFirstTimeout);
429 
430     // We are on mock time. There is no time advancement and as such no hangs.
431     ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
432     ASSERT_EQ(current_hang_watch_state->GetDeadline(), first_deadline);
433     {
434       // Set a yet more restrictive deadline. Still no hang.
435       WatchHangsInScope second_scope(kSecondTimeout);
436       ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
437       ASSERT_EQ(current_hang_watch_state->GetDeadline(), second_deadline);
438     }
439     // First deadline we set should be restored.
440     ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
441     ASSERT_EQ(current_hang_watch_state->GetDeadline(), first_deadline);
442   }
443 
444   // Original deadline should now be restored.
445   ASSERT_FALSE(current_hang_watch_state->IsOverDeadline());
446   ASSERT_EQ(current_hang_watch_state->GetDeadline(), original_deadline);
447 }
448 
TEST_F(HangWatcherBlockingThreadTest,HistogramsLoggedOnHang)449 TEST_F(HangWatcherBlockingThreadTest, HistogramsLoggedOnHang) {
450   base::HistogramTester histogram_tester;
451   StartBlockedThread();
452 
453   // Simulate hang.
454   task_environment_.FastForwardBy(kHangTime);
455 
456   // First monitoring catches the hang and emits the histogram.
457   MonitorHangs();
458   EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
459                                              "BrowserProcess.UIThread.Normal"),
460               ElementsAre(base::Bucket(true, /*count=*/1)));
461 
462   // Reset to attempt capture again.
463   hang_event_.Reset();
464   monitor_event_.Reset();
465 
466   // Hang is logged again even if it would not trigger a crash dump.
467   MonitorHangs();
468   EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
469                                              "BrowserProcess.UIThread.Normal"),
470               ElementsAre(base::Bucket(true, /*count=*/2)));
471 
472   // Thread types that are not monitored should not get any samples.
473   EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
474                                              "BrowserProcess.IOThread.Normal"),
475               IsEmpty());
476 
477   // No shutdown hangs, either.
478   EXPECT_THAT(histogram_tester.GetAllSamples(
479                   "HangWatcher.IsThreadHung.BrowserProcess.UIThread.Shutdown"),
480               IsEmpty());
481   EXPECT_THAT(histogram_tester.GetAllSamples(
482                   "HangWatcher.IsThreadHung.BrowserProcess.IOThread.Shutdown"),
483               IsEmpty());
484 
485   JoinThread();
486 }
487 
TEST_F(HangWatcherBlockingThreadTest,HistogramsLoggedWithoutHangs)488 TEST_F(HangWatcherBlockingThreadTest, HistogramsLoggedWithoutHangs) {
489   base::HistogramTester histogram_tester;
490   StartBlockedThread();
491 
492   // No hang to catch so nothing is recorded.
493   MonitorHangs();
494   ASSERT_FALSE(hang_event_.IsSignaled());
495 
496   // A thread of type ThreadForTesting was monitored but didn't hang. This is
497   // logged.
498   EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
499                                              "BrowserProcess.UIThread.Normal"),
500               ElementsAre(base::Bucket(false, /*count=*/1)));
501 
502   // Thread types that are not monitored should not get any samples.
503   EXPECT_THAT(histogram_tester.GetAllSamples("HangWatcher.IsThreadHung."
504                                              "BrowserProcess.IOThread.Normal"),
505               IsEmpty());
506   JoinThread();
507 }
508 
TEST_F(HangWatcherBlockingThreadTest,HistogramsLoggedWithShutdownFlag)509 TEST_F(HangWatcherBlockingThreadTest, HistogramsLoggedWithShutdownFlag) {
510   base::HistogramTester histogram_tester;
511   StartBlockedThread();
512 
513   // Simulate hang.
514   task_environment_.FastForwardBy(kHangTime);
515 
516   // Make this process emit *.Shutdown instead of *.Normal histograms.
517   base::HangWatcher::SetShuttingDown();
518 
519   // First monitoring catches the hang and emits the histogram.
520   MonitorHangs();
521   EXPECT_THAT(histogram_tester.GetAllSamples(
522                   "HangWatcher.IsThreadHung.BrowserProcess.UIThread.Shutdown"),
523               ElementsAre(base::Bucket(true, /*count=*/1)));
524 
525   // Reset to attempt capture again.
526   hang_event_.Reset();
527   monitor_event_.Reset();
528 
529   // Hang is logged again even if it would not trigger a crash dump.
530   MonitorHangs();
531   EXPECT_THAT(histogram_tester.GetAllSamples(
532                   "HangWatcher.IsThreadHung.BrowserProcess.UIThread.Shutdown"),
533               ElementsAre(base::Bucket(true, /*count=*/2)));
534 
535   // Thread types that are not monitored should not get any samples.
536   EXPECT_THAT(histogram_tester.GetAllSamples(
537                   "HangWatcher.IsThreadHung.BrowserProcess.IOThread.Shutdown"),
538               IsEmpty());
539 
540   // No normal hangs.
541   EXPECT_THAT(histogram_tester.GetAllSamples(
542                   "HangWatcher.IsThreadHung.BrowserProcess.UIThread.Normal"),
543               IsEmpty());
544   EXPECT_THAT(histogram_tester.GetAllSamples(
545                   "HangWatcher.IsThreadHung.BrowserProcess.IOThread.Normal"),
546               IsEmpty());
547 
548   JoinThread();
549 }
550 
TEST_F(HangWatcherBlockingThreadTest,Hang)551 TEST_F(HangWatcherBlockingThreadTest, Hang) {
552   StartBlockedThread();
553 
554   // Simulate hang.
555   task_environment_.FastForwardBy(kHangTime);
556 
557   // First monitoring catches and records the hang.
558   MonitorHangs();
559   ASSERT_TRUE(hang_event_.IsSignaled());
560 
561   JoinThread();
562 }
563 
TEST_F(HangWatcherBlockingThreadTest,HangAlreadyRecorded)564 TEST_F(HangWatcherBlockingThreadTest, HangAlreadyRecorded) {
565   StartBlockedThread();
566 
567   // Simulate hang.
568   task_environment_.FastForwardBy(kHangTime);
569 
570   // First monitoring catches and records the hang.
571   MonitorHangs();
572   ASSERT_TRUE(hang_event_.IsSignaled());
573 
574   // Reset to attempt capture again.
575   hang_event_.Reset();
576   monitor_event_.Reset();
577 
578   // Second monitoring does not record because a hang that was already recorded
579   // is still live.
580   MonitorHangs();
581   ASSERT_FALSE(hang_event_.IsSignaled());
582 
583   JoinThread();
584 }
585 
TEST_F(HangWatcherBlockingThreadTest,NoHang)586 TEST_F(HangWatcherBlockingThreadTest, NoHang) {
587   StartBlockedThread();
588 
589   // No hang to catch so nothing is recorded.
590   MonitorHangs();
591   ASSERT_FALSE(hang_event_.IsSignaled());
592 
593   JoinThread();
594 }
595 
596 namespace {
597 class HangWatcherSnapshotTest : public testing::Test {
598  public:
SetUp()599   void SetUp() override {
600     feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
601     HangWatcher::InitializeOnMainThread(
602         HangWatcher::ProcessType::kBrowserProcess, /*emit_crashes=*/true);
603 
604     // The monitoring loop behavior is not verified in this test so we want to
605     // trigger monitoring manually.
606     hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
607   }
608 
TearDown()609   void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
610 
611   HangWatcherSnapshotTest() = default;
612   HangWatcherSnapshotTest(const HangWatcherSnapshotTest& other) = delete;
613   HangWatcherSnapshotTest& operator=(const HangWatcherSnapshotTest& other) =
614       delete;
615 
616  protected:
TriggerMonitorAndWaitForCompletion()617   void TriggerMonitorAndWaitForCompletion() {
618     monitor_event_.Reset();
619     hang_watcher_.SignalMonitorEventForTesting();
620     monitor_event_.Wait();
621   }
622 
623   // Verify that a capture takes place and that at the time of the capture the
624   // list of hung thread ids is correct.
TestIDList(const std::string & id_list)625   void TestIDList(const std::string& id_list) {
626     list_of_hung_thread_ids_during_capture_ = id_list;
627     task_environment_.AdvanceClock(kSmallCPUQuantum);
628     TriggerMonitorAndWaitForCompletion();
629     ASSERT_EQ(++reference_capture_count_, hang_capture_count_);
630   }
631 
632   // Verify that even if hang monitoring takes place no hangs are detected.
ExpectNoCapture()633   void ExpectNoCapture() {
634     int old_capture_count = hang_capture_count_;
635     task_environment_.AdvanceClock(kSmallCPUQuantum);
636     TriggerMonitorAndWaitForCompletion();
637     ASSERT_EQ(old_capture_count, hang_capture_count_);
638   }
639 
ConcatenateThreadIds(const std::vector<base::PlatformThreadId> & ids) const640   std::string ConcatenateThreadIds(
641       const std::vector<base::PlatformThreadId>& ids) const {
642     std::string result;
643     constexpr char kSeparator{'|'};
644 
645     for (PlatformThreadId id : ids) {
646       result += base::NumberToString(id) + kSeparator;
647     }
648 
649     return result;
650   }
651 
652   // Will be signaled once monitoring took place. Marks the end of the test.
653   WaitableEvent monitor_event_;
654 
655   const PlatformThreadId test_thread_id_ = PlatformThread::CurrentId();
656 
657   // This is written to by the test main thread and read from the hang watching
658   // thread. It does not need to be protected because access to it is
659   // synchronized by always setting before triggering the execution of the
660   // reading code through HangWatcher::SignalMonitorEventForTesting().
661   std::string list_of_hung_thread_ids_during_capture_;
662 
663   // This is written to by from the hang watching thread and read the test main
664   // thread. It does not need to be protected because access to it is
665   // synchronized by always reading  after monitor_event_ has been signaled.
666   int hang_capture_count_ = 0;
667 
668   // Increases at the same time as |hang_capture_count_| to test that capture
669   // actually took place.
670   int reference_capture_count_ = 0;
671 
672   std::string seconds_since_last_power_resume_crash_key_;
673 
674   base::test::ScopedFeatureList feature_list_;
675 
676   // Used exclusively for MOCK_TIME.
677   test::SingleThreadTaskEnvironment task_environment_{
678       test::TaskEnvironment::TimeSource::MOCK_TIME};
679 
680   HangWatcher hang_watcher_;
681 };
682 }  // namespace
683 
684 // Verify that the hang capture fails when marking a thread for blocking fails.
685 // This simulates a WatchHangsInScope completing between the time the hang
686 // was dected and the time it is recorded which would create a non-actionable
687 // report.
TEST_F(HangWatcherSnapshotTest,NonActionableReport)688 TEST_F(HangWatcherSnapshotTest, NonActionableReport) {
689   hang_watcher_.SetOnHangClosureForTesting(
690       base::BindLambdaForTesting([this] { ++hang_capture_count_; }));
691   hang_watcher_.SetAfterMonitorClosureForTesting(
692       base::BindLambdaForTesting([this] { monitor_event_.Signal(); }));
693 
694   hang_watcher_.Start();
695 
696   // Register the main test thread for hang watching.
697   auto unregister_thread_closure =
698       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
699   {
700     // Start a WatchHangsInScope that expires right away. Ensures that
701     // the first monitor will detect a hang.
702     WatchHangsInScope expires_instantly(base::TimeDelta{});
703 
704     internal::HangWatchState* current_hang_watch_state =
705         internal::HangWatchState::GetHangWatchStateForCurrentThread();
706 
707     // Simulate the deadline changing concurrently during the capture. This
708     // makes the capture fail since marking of the deadline fails.
709     ASSERT_NE(current_hang_watch_state->GetDeadline(),
710               base::TimeTicks::FromInternalValue(kArbitraryDeadline));
711     current_hang_watch_state->GetHangWatchDeadlineForTesting()
712         ->SetSwitchBitsClosureForTesting(
713             base::BindLambdaForTesting([] { return kArbitraryDeadline; }));
714 
715     ExpectNoCapture();
716 
717     // Marking failed.
718     ASSERT_FALSE(current_hang_watch_state->IsFlagSet(
719         internal::HangWatchDeadline::Flag::kShouldBlockOnHang));
720 
721     current_hang_watch_state->GetHangWatchDeadlineForTesting()
722         ->ResetSwitchBitsClosureForTesting();
723   }
724 }
725 
726 // TODO(crbug.com/40187449): On MAC, the base::PlatformThread::CurrentId(...)
727 // should return the system wide IDs. The HungThreadIDs test fails because the
728 // reported process ids do not match.
729 #if BUILDFLAG(IS_MAC)
730 #define MAYBE_HungThreadIDs DISABLED_HungThreadIDs
731 #else
732 #define MAYBE_HungThreadIDs HungThreadIDs
733 #endif
734 
TEST_F(HangWatcherSnapshotTest,MAYBE_HungThreadIDs)735 TEST_F(HangWatcherSnapshotTest, MAYBE_HungThreadIDs) {
736   // During hang capture the list of hung threads should be populated.
737   hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([this] {
738     EXPECT_EQ(hang_watcher_.GrabWatchStateSnapshotForTesting()
739                   .PrepareHungThreadListCrashKey(),
740               list_of_hung_thread_ids_during_capture_);
741     ++hang_capture_count_;
742   }));
743 
744   // When hang capture is over the list should be empty.
745   hang_watcher_.SetAfterMonitorClosureForTesting(
746       base::BindLambdaForTesting([this] { monitor_event_.Signal(); }));
747 
748   hang_watcher_.Start();
749 
750   // Register the main test thread for hang watching.
751   auto unregister_thread_closure =
752       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
753 
754   BlockingThread blocking_thread(&monitor_event_, base::TimeDelta{});
755   blocking_thread.StartAndWaitForScopeEntered();
756   {
757     // Ensure the blocking thread entered the scope before the main thread. This
758     // will guarantee an ordering while reporting the list of hung threads.
759     task_environment_.AdvanceClock(kSmallCPUQuantum);
760 
761     // Start a WatchHangsInScope that expires right away. Ensures that
762     // the first monitor will detect a hang. This scope will naturally have a
763     // later deadline than the one in |blocking_thread_| since it was created
764     // after.
765     WatchHangsInScope expires_instantly(base::TimeDelta{});
766 
767     // Hung thread list should contain the id the blocking thread and then the
768     // id of the test main thread since that is the order of increasing
769     // deadline.
770     TestIDList(
771         ConcatenateThreadIds({blocking_thread.GetId(), test_thread_id_}));
772 
773     // |expires_instantly| and the scope from |blocking_thread| are still live
774     // but already recorded so should be ignored.
775     ExpectNoCapture();
776 
777     // Thread is joinable since we signaled |monitor_event_|. This closes the
778     // scope in |blocking_thread|.
779     blocking_thread.Join();
780 
781     // |expires_instantly| is still live but already recorded so should be
782     // ignored.
783     ExpectNoCapture();
784   }
785 
786   // All HangWatchScopeEnables are over. There should be no capture.
787   ExpectNoCapture();
788 
789   // Once all recorded scopes are over creating a new one and monitoring will
790   // trigger a hang detection.
791   WatchHangsInScope expires_instantly(base::TimeDelta{});
792   TestIDList(ConcatenateThreadIds({test_thread_id_}));
793 }
794 
TEST_F(HangWatcherSnapshotTest,TimeSinceLastSystemPowerResumeCrashKey)795 TEST_F(HangWatcherSnapshotTest, TimeSinceLastSystemPowerResumeCrashKey) {
796   // Override the capture of hangs. Simulate a crash key capture.
797   hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([this] {
798     ++hang_capture_count_;
799     seconds_since_last_power_resume_crash_key_ =
800         hang_watcher_.GetTimeSinceLastSystemPowerResumeCrashKeyValue();
801   }));
802 
803   // When hang capture is over, unblock the main thread.
804   hang_watcher_.SetAfterMonitorClosureForTesting(
805       base::BindLambdaForTesting([this] { monitor_event_.Signal(); }));
806 
807   hang_watcher_.Start();
808 
809   // Register the main test thread for hang watching.
810   auto unregister_thread_closure =
811       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
812 
813   {
814     WatchHangsInScope expires_instantly(base::TimeDelta{});
815     task_environment_.AdvanceClock(kSmallCPUQuantum);
816 
817     TriggerMonitorAndWaitForCompletion();
818     EXPECT_EQ(1, hang_capture_count_);
819     EXPECT_EQ("Never suspended", seconds_since_last_power_resume_crash_key_);
820   }
821 
822   {
823     test::ScopedPowerMonitorTestSource power_monitor_source;
824     power_monitor_source.Suspend();
825     task_environment_.AdvanceClock(kSmallCPUQuantum);
826 
827     {
828       WatchHangsInScope expires_instantly(base::TimeDelta{});
829       task_environment_.AdvanceClock(kSmallCPUQuantum);
830       TriggerMonitorAndWaitForCompletion();
831       EXPECT_EQ(2, hang_capture_count_);
832       EXPECT_EQ("Power suspended", seconds_since_last_power_resume_crash_key_);
833     }
834 
835     power_monitor_source.Resume();
836     constexpr TimeDelta kAfterResumeTime{base::Seconds(5)};
837     task_environment_.AdvanceClock(kAfterResumeTime);
838 
839     {
840       WatchHangsInScope expires_instantly(base::TimeDelta{});
841       TriggerMonitorAndWaitForCompletion();
842       EXPECT_EQ(3, hang_capture_count_);
843       EXPECT_EQ(base::NumberToString(kAfterResumeTime.InSeconds()),
844                 seconds_since_last_power_resume_crash_key_);
845     }
846   }
847 }
848 
849 namespace {
850 
851 // Determines how long the HangWatcher will wait between calls to
852 // Monitor(). Choose a low value so that that successive invocations happens
853 // fast. This makes tests that wait for monitoring run fast and makes tests that
854 // expect no monitoring fail fast.
855 const base::TimeDelta kMonitoringPeriod = base::Milliseconds(1);
856 
857 // Test if and how often the HangWatcher periodically monitors for hangs.
858 class HangWatcherPeriodicMonitoringTest : public testing::Test {
859  public:
HangWatcherPeriodicMonitoringTest()860   HangWatcherPeriodicMonitoringTest() {
861     hang_watcher_.InitializeOnMainThread(
862         HangWatcher::ProcessType::kBrowserProcess, /*emit_crashes=*/true);
863 
864     hang_watcher_.SetMonitoringPeriodForTesting(kMonitoringPeriod);
865     hang_watcher_.SetOnHangClosureForTesting(base::BindRepeating(
866         &WaitableEvent::Signal, base::Unretained(&hang_event_)));
867 
868     // HangWatcher uses a TickClock to detect how long it slept in between calls
869     // to Monitor(). Override that clock to control its subjective passage of
870     // time.
871     hang_watcher_.SetTickClockForTesting(&test_clock_);
872   }
873 
874   HangWatcherPeriodicMonitoringTest(
875       const HangWatcherPeriodicMonitoringTest& other) = delete;
876   HangWatcherPeriodicMonitoringTest& operator=(
877       const HangWatcherPeriodicMonitoringTest& other) = delete;
878 
TearDown()879   void TearDown() override { hang_watcher_.UnitializeOnMainThreadForTesting(); }
880 
881  protected:
882   // Setup the callback invoked after waiting in HangWatcher to advance the
883   // tick clock by the desired time delta.
InstallAfterWaitCallback(base::TimeDelta time_delta)884   void InstallAfterWaitCallback(base::TimeDelta time_delta) {
885     hang_watcher_.SetAfterWaitCallbackForTesting(base::BindLambdaForTesting(
886         [this, time_delta](base::TimeTicks time_before_wait) {
887           test_clock_.Advance(time_delta);
888         }));
889   }
890 
891   base::SimpleTestTickClock test_clock_;
892 
893   // Single threaded to avoid ThreadPool WorkerThreads registering. Will run
894   // delayed tasks created by the tests.
895   test::SingleThreadTaskEnvironment task_environment_;
896 
897   std::unique_ptr<base::TickClock> fake_tick_clock_;
898   HangWatcher hang_watcher_;
899 
900   // Signaled when a hang is detected.
901   WaitableEvent hang_event_;
902 
903   base::ScopedClosureRunner unregister_thread_closure_;
904 };
905 }  // namespace
906 
907 // Don't register any threads for hang watching. HangWatcher should not monitor.
TEST_F(HangWatcherPeriodicMonitoringTest,NoPeriodicMonitoringWithoutRegisteredThreads)908 TEST_F(HangWatcherPeriodicMonitoringTest,
909        NoPeriodicMonitoringWithoutRegisteredThreads) {
910   RunLoop run_loop;
911 
912   // If a call to HangWatcher::Monitor() takes place the test will instantly
913   // fail.
914   hang_watcher_.SetAfterMonitorClosureForTesting(
915       base::BindLambdaForTesting([&run_loop] {
916         ADD_FAILURE() << "Monitoring took place!";
917         run_loop.Quit();
918       }));
919 
920   // Make the HangWatcher tick clock advance by exactly the monitoring period
921   // after waiting so it will never detect oversleeping between attempts to call
922   // Monitor(). This would inhibit monitoring and make the test pass for the
923   // wrong reasons.
924   InstallAfterWaitCallback(kMonitoringPeriod);
925 
926   hang_watcher_.Start();
927 
928   // Unblock the test thread. No thread ever registered after the HangWatcher
929   // was created in the test's constructor. No monitoring should have taken
930   // place.
931   task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
932       FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
933   run_loop.Run();
934 
935   // NOTE:
936   // A lack of calls could technically also be caused by the HangWatcher thread
937   // executing too slowly / being descheduled. This is a known limitation.
938   // It's expected for |TestTimeouts::tiny_timeout()| to be large enough that
939   // this is rare.
940 }
941 
942 // During normal execution periodic monitorings should take place.
TEST_F(HangWatcherPeriodicMonitoringTest,PeriodicCallsTakePlace)943 TEST_F(HangWatcherPeriodicMonitoringTest, PeriodicCallsTakePlace) {
944   // HangWatcher::Monitor() will run once right away on thread registration.
945   // We want to make sure it runs at a couple more times from being scheduled.
946   constexpr int kMinimumMonitorCount = 3;
947 
948   RunLoop run_loop;
949 
950   // Setup the HangWatcher to unblock run_loop when the Monitor() has been
951   // invoked enough times.
952   hang_watcher_.SetAfterMonitorClosureForTesting(BarrierClosure(
953       kMinimumMonitorCount, base::BindLambdaForTesting([&run_loop] {
954         // Test condition are confirmed, stop monitoring.
955         HangWatcher::StopMonitoringForTesting();
956 
957         // Unblock the test main thread.
958         run_loop.Quit();
959       })));
960 
961   // Make the HangWatcher tick clock advance by exactly the monitoring period
962   // after waiting so it will never detect oversleeping between attempts to call
963   // Monitor(). This would inhibit monitoring.
964   InstallAfterWaitCallback(kMonitoringPeriod);
965 
966   hang_watcher_.Start();
967 
968   // Register a thread,
969   unregister_thread_closure_ =
970       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
971 
972   run_loop.Run();
973 
974   // No monitored scope means no possible hangs.
975   ASSERT_FALSE(hang_event_.IsSignaled());
976 }
977 
978 // If the HangWatcher detects it slept for longer than expected it will not
979 // monitor.
TEST_F(HangWatcherPeriodicMonitoringTest,NoMonitorOnOverSleep)980 TEST_F(HangWatcherPeriodicMonitoringTest, NoMonitorOnOverSleep) {
981   RunLoop run_loop;
982 
983   // If a call to HangWatcher::Monitor() takes place the test will instantly
984   // fail.
985   hang_watcher_.SetAfterMonitorClosureForTesting(
986       base::BindLambdaForTesting([&run_loop] {
987         ADD_FAILURE() << "Monitoring took place!";
988         run_loop.Quit();
989       }));
990 
991   // Make the HangWatcher tick clock advance so much after waiting that it will
992   // detect oversleeping every time. This will keep it from monitoring.
993   InstallAfterWaitCallback(base::Minutes(1));
994 
995   hang_watcher_.Start();
996 
997   // Register a thread.
998   unregister_thread_closure_ =
999       HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
1000 
1001   // Unblock the test thread. All waits were perceived as oversleeping so all
1002   // monitoring was inhibited.
1003   task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
1004       FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
1005   run_loop.Run();
1006 
1007   // NOTE: A lack of calls could technically also be caused by the HangWatcher
1008   // thread executing too slowly / being descheduled. This is a known
1009   // limitation. It's expected for |TestTimeouts::tiny_timeout()| to be large
1010   // enough that this happens rarely.
1011 }
1012 
1013 namespace {
1014 class WatchHangsInScopeBlockingTest : public testing::Test {
1015  public:
WatchHangsInScopeBlockingTest()1016   WatchHangsInScopeBlockingTest() {
1017     feature_list_.InitWithFeaturesAndParameters(kFeatureAndParams, {});
1018     HangWatcher::InitializeOnMainThread(
1019         HangWatcher::ProcessType::kBrowserProcess, /*emit_crashes=*/true);
1020 
1021     hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([&] {
1022       capture_started_.Signal();
1023       // Simulate capturing that takes a long time.
1024       PlatformThread::Sleep(base::Milliseconds(500));
1025 
1026       continue_capture_.Wait();
1027       completed_capture_ = true;
1028     }));
1029 
1030     hang_watcher_.SetAfterMonitorClosureForTesting(
1031         base::BindLambdaForTesting([&] {
1032           // Simulate monitoring that takes a long time.
1033           PlatformThread::Sleep(base::Milliseconds(500));
1034           completed_monitoring_.Signal();
1035         }));
1036 
1037     // Make sure no periodic monitoring takes place.
1038     hang_watcher_.SetMonitoringPeriodForTesting(kVeryLongDelta);
1039 
1040     hang_watcher_.Start();
1041 
1042     // Register the test main thread for hang watching.
1043     unregister_thread_closure_ =
1044         HangWatcher::RegisterThread(base::HangWatcher::ThreadType::kMainThread);
1045   }
1046 
TearDown()1047   void TearDown() override { HangWatcher::UnitializeOnMainThreadForTesting(); }
1048 
1049   WatchHangsInScopeBlockingTest(const WatchHangsInScopeBlockingTest& other) =
1050       delete;
1051   WatchHangsInScopeBlockingTest& operator=(
1052       const WatchHangsInScopeBlockingTest& other) = delete;
1053 
VerifyScopesDontBlock()1054   void VerifyScopesDontBlock() {
1055     // Start a WatchHangsInScope that cannot possibly cause a hang to be
1056     // detected.
1057     {
1058       WatchHangsInScope long_scope(kVeryLongDelta);
1059 
1060       // Manually trigger a monitoring.
1061       hang_watcher_.SignalMonitorEventForTesting();
1062 
1063       // Execution has to continue freely here as no capture is in progress.
1064     }
1065 
1066     // Monitoring should not be over yet because the test code should execute
1067     // faster when not blocked.
1068     EXPECT_FALSE(completed_monitoring_.IsSignaled());
1069 
1070     // Wait for the full monitoring process to be complete. This is to prove
1071     // that monitoring truly executed and that we raced the signaling.
1072     completed_monitoring_.Wait();
1073 
1074     // No hang means no capture.
1075     EXPECT_FALSE(completed_capture_);
1076   }
1077 
1078  protected:
1079   base::WaitableEvent capture_started_;
1080   base::WaitableEvent completed_monitoring_;
1081 
1082   // The HangWatcher waits on this event via the "on hang" closure when a hang
1083   // is detected.
1084   base::WaitableEvent continue_capture_;
1085   bool completed_capture_{false};
1086 
1087   base::test::ScopedFeatureList feature_list_;
1088   HangWatcher hang_watcher_;
1089   base::ScopedClosureRunner unregister_thread_closure_;
1090 };
1091 }  // namespace
1092 
1093 // Tests that execution is unimpeded by ~WatchHangsInScope() when no capture
1094 // ever takes place.
TEST_F(WatchHangsInScopeBlockingTest,ScopeDoesNotBlocksWithoutCapture)1095 TEST_F(WatchHangsInScopeBlockingTest, ScopeDoesNotBlocksWithoutCapture) {
1096   // No capture should take place so |continue_capture_| is not signaled to
1097   // create a test hang if one ever does.
1098   VerifyScopesDontBlock();
1099 }
1100 
1101 // Test that execution blocks in ~WatchHangsInScope() for a thread under
1102 // watch during the capturing of a hang.
TEST_F(WatchHangsInScopeBlockingTest,ScopeBlocksDuringCapture)1103 TEST_F(WatchHangsInScopeBlockingTest, ScopeBlocksDuringCapture) {
1104   // The capture completing is not dependent on any test event. Signal to make
1105   // sure the test is not blocked.
1106   continue_capture_.Signal();
1107 
1108   // Start a WatchHangsInScope that expires in the past already. Ensures
1109   // that the first monitor will detect a hang.
1110   {
1111     // Start a WatchHangsInScope that expires right away. Ensures that the
1112     // first monitor will detect a hang.
1113     WatchHangsInScope expires_right_away(base::TimeDelta{});
1114 
1115     // Manually trigger a monitoring.
1116     hang_watcher_.SignalMonitorEventForTesting();
1117 
1118     // Ensure that the hang capturing started.
1119     capture_started_.Wait();
1120 
1121     // Execution will get stuck in the outer scope because it can't escape
1122     // ~WatchHangsInScope() if a hang capture is under way.
1123   }
1124 
1125   // A hang was in progress so execution should have been blocked in
1126   // BlockWhileCaptureInProgress() until capture finishes.
1127   EXPECT_TRUE(completed_capture_);
1128   completed_monitoring_.Wait();
1129 
1130   // Reset expectations
1131   completed_monitoring_.Reset();
1132   capture_started_.Reset();
1133   completed_capture_ = false;
1134 
1135   // Verify that scopes don't block just because a capture happened in the past.
1136   VerifyScopesDontBlock();
1137 }
1138 
1139 #if BUILDFLAG(IS_MAC) && defined(ARCH_CPU_ARM64)
1140 // Flaky hangs on arm64 Macs: https://crbug.com/1140207
1141 #define MAYBE_NewScopeDoesNotBlockDuringCapture \
1142   DISABLED_NewScopeDoesNotBlockDuringCapture
1143 #else
1144 #define MAYBE_NewScopeDoesNotBlockDuringCapture \
1145   NewScopeDoesNotBlockDuringCapture
1146 #endif
1147 
1148 // Test that execution does not block in ~WatchHangsInScope() when the scope
1149 // was created after the start of a capture.
TEST_F(WatchHangsInScopeBlockingTest,MAYBE_NewScopeDoesNotBlockDuringCapture)1150 TEST_F(WatchHangsInScopeBlockingTest, MAYBE_NewScopeDoesNotBlockDuringCapture) {
1151   // Start a WatchHangsInScope that expires right away. Ensures that the
1152   // first monitor will detect a hang.
1153   WatchHangsInScope expires_right_away(base::TimeDelta{});
1154 
1155   // Manually trigger a monitoring.
1156   hang_watcher_.SignalMonitorEventForTesting();
1157 
1158   // Ensure that the hang capturing started.
1159   capture_started_.Wait();
1160 
1161   // A scope started once a capture is already under way should not block
1162   // execution.
1163   { WatchHangsInScope also_expires_right_away(base::TimeDelta{}); }
1164 
1165   // Wait for the new WatchHangsInScope to be destroyed to let the capture
1166   // finish. If the new scope block waiting for the capture to finish this would
1167   // create a deadlock and the test would hang.
1168   continue_capture_.Signal();
1169 }
1170 
1171 namespace internal {
1172 namespace {
1173 
1174 constexpr std::array<HangWatchDeadline::Flag, 3> kAllFlags{
1175     {HangWatchDeadline::Flag::kMinValue,
1176      HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope,
1177      HangWatchDeadline::Flag::kShouldBlockOnHang}};
1178 }  // namespace
1179 
1180 class HangWatchDeadlineTest : public testing::Test {
1181  protected:
AssertNoFlagsSet() const1182   void AssertNoFlagsSet() const {
1183     for (HangWatchDeadline::Flag flag : kAllFlags) {
1184       ASSERT_FALSE(deadline_.IsFlagSet(flag));
1185     }
1186   }
1187 
1188   // Return a flag mask without one of the flags for test purposes. Use to
1189   // ignore that effect of setting a flag that was just set.
FlagsMinus(uint64_t flags,HangWatchDeadline::Flag flag)1190   uint64_t FlagsMinus(uint64_t flags, HangWatchDeadline::Flag flag) {
1191     return flags & ~(static_cast<uint64_t>(flag));
1192   }
1193 
1194   HangWatchDeadline deadline_;
1195 };
1196 
1197 // Verify that the extract functions don't mangle any bits.
TEST_F(HangWatchDeadlineTest,BitsPreservedThroughExtract)1198 TEST_F(HangWatchDeadlineTest, BitsPreservedThroughExtract) {
1199   for (auto bits : {kAllOnes, kAllZeros, kOnesThenZeroes, kZeroesThenOnes}) {
1200     ASSERT_TRUE((HangWatchDeadline::ExtractFlags(bits) |
1201                  HangWatchDeadline::ExtractDeadline(bits)) == bits);
1202   }
1203 }
1204 
1205 // Verify that setting and clearing a persistent flag works and has no unwanted
1206 // side-effects. Neither the flags nor the deadline change concurrently in this
1207 // test.
TEST_F(HangWatchDeadlineTest,SetAndClearPersistentFlag)1208 TEST_F(HangWatchDeadlineTest, SetAndClearPersistentFlag) {
1209   AssertNoFlagsSet();
1210 
1211   // Grab the original values for flags and deadline.
1212   auto [old_flags, old_deadline] = deadline_.GetFlagsAndDeadline();
1213 
1214   // Set the flag. Operation cannot fail.
1215   deadline_.SetIgnoreCurrentWatchHangsInScope();
1216 
1217   // Get new flags and deadline.
1218   auto [new_flags, new_deadline] = deadline_.GetFlagsAndDeadline();
1219 
1220   // Flag was set properly.
1221   ASSERT_TRUE(HangWatchDeadline::IsFlagSet(
1222       HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope, new_flags));
1223 
1224   // No side-effect on deadline.
1225   ASSERT_EQ(new_deadline, old_deadline);
1226 
1227   // No side-effect on other flags.
1228   ASSERT_EQ(
1229       FlagsMinus(new_flags,
1230                  HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope),
1231       old_flags);
1232 
1233   // Clear the flag, operation cannot fail.
1234   deadline_.UnsetIgnoreCurrentWatchHangsInScope();
1235 
1236   // Update new values.
1237   std::tie(new_flags, new_deadline) = deadline_.GetFlagsAndDeadline();
1238 
1239   // All flags back to original state.
1240   ASSERT_EQ(new_flags, old_flags);
1241 
1242   // Deadline still unnafected.
1243   ASSERT_EQ(new_deadline, old_deadline);
1244 }
1245 
1246 // Verify setting the TimeTicks value works and has no unwanted side-effects.
TEST_F(HangWatchDeadlineTest,SetDeadline)1247 TEST_F(HangWatchDeadlineTest, SetDeadline) {
1248   TimeTicks ticks;
1249 
1250   AssertNoFlagsSet();
1251   ASSERT_NE(deadline_.GetDeadline(), ticks);
1252 
1253   // Set the deadline and verify it stuck.
1254   deadline_.SetDeadline(ticks);
1255   ASSERT_EQ(deadline_.GetDeadline(), ticks);
1256 
1257   // Only the value was modified, no flags should be set.
1258   AssertNoFlagsSet();
1259 }
1260 
1261 // Verify that setting a non-persistent flag (kShouldBlockOnHang)
1262 // when the TimeTicks value changed since calling the flag setting
1263 // function fails and has no side-effects.
TEST_F(HangWatchDeadlineTest,SetShouldBlockOnHangDeadlineChanged)1264 TEST_F(HangWatchDeadlineTest, SetShouldBlockOnHangDeadlineChanged) {
1265   AssertNoFlagsSet();
1266 
1267   auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1268 
1269   // Simulate value change. Flags are constant.
1270   const base::TimeTicks new_deadline =
1271       base::TimeTicks::FromInternalValue(kArbitraryDeadline);
1272   ASSERT_NE(deadline, new_deadline);
1273   deadline_.SetSwitchBitsClosureForTesting(
1274       base::BindLambdaForTesting([] { return kArbitraryDeadline; }));
1275 
1276   // kShouldBlockOnHangs does not persist through value change.
1277   ASSERT_FALSE(deadline_.SetShouldBlockOnHang(flags, deadline));
1278 
1279   // Flag was not applied.
1280   ASSERT_FALSE(
1281       deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1282 
1283   // New value that was changed concurrently is preserved.
1284   ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
1285 }
1286 
1287 // Verify that clearing a persistent (kIgnoreCurrentWatchHangsInScope) when
1288 // the value changed succeeds and has non side-effects.
TEST_F(HangWatchDeadlineTest,ClearIgnoreHangsDeadlineChanged)1289 TEST_F(HangWatchDeadlineTest, ClearIgnoreHangsDeadlineChanged) {
1290   AssertNoFlagsSet();
1291 
1292   auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1293 
1294   deadline_.SetIgnoreCurrentWatchHangsInScope();
1295   std::tie(flags, deadline) = deadline_.GetFlagsAndDeadline();
1296   ASSERT_TRUE(HangWatchDeadline::IsFlagSet(
1297       HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope, flags));
1298 
1299   // Simulate deadline change. Flags are constant.
1300   const base::TimeTicks new_deadline =
1301       base::TimeTicks::FromInternalValue(kArbitraryDeadline);
1302   ASSERT_NE(deadline, new_deadline);
1303   deadline_.SetSwitchBitsClosureForTesting(base::BindLambdaForTesting([] {
1304     return static_cast<uint64_t>(HangWatchDeadline::Flag::kShouldBlockOnHang) |
1305            kArbitraryDeadline;
1306   }));
1307 
1308   // Clearing kIgnoreHang is unaffected by deadline or flags change.
1309   deadline_.UnsetIgnoreCurrentWatchHangsInScope();
1310   ASSERT_FALSE(deadline_.IsFlagSet(
1311       HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1312 
1313   // New deadline that was changed concurrently is preserved.
1314   ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1315   ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
1316 }
1317 
1318 // Verify that setting a persistent (kIgnoreCurrentWatchHangsInScope) when
1319 // the deadline or flags changed succeeds and has non side-effects.
TEST_F(HangWatchDeadlineTest,SetIgnoreCurrentHangWatchScopeEnableDeadlineChangedd)1320 TEST_F(HangWatchDeadlineTest,
1321        SetIgnoreCurrentHangWatchScopeEnableDeadlineChangedd) {
1322   AssertNoFlagsSet();
1323 
1324   auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1325 
1326   // Simulate deadline change. Flags are constant.
1327   const base::TimeTicks new_deadline =
1328       base::TimeTicks::FromInternalValue(kArbitraryDeadline);
1329 
1330   ASSERT_NE(deadline, new_deadline);
1331   deadline_.SetSwitchBitsClosureForTesting(base::BindLambdaForTesting([] {
1332     return static_cast<uint64_t>(HangWatchDeadline::Flag::kShouldBlockOnHang) |
1333            kArbitraryDeadline;
1334   }));
1335 
1336   // kIgnoreHang persists through value change.
1337   deadline_.SetIgnoreCurrentWatchHangsInScope();
1338   ASSERT_TRUE(deadline_.IsFlagSet(
1339       HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1340 
1341   // New deadline and flags that changed concurrently are preserved.
1342   ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1343   ASSERT_EQ(deadline_.GetDeadline(), new_deadline);
1344 }
1345 
1346 // Setting a new deadline should wipe flags that a not persistent.
1347 // Persistent flags should not be disturbed.
TEST_F(HangWatchDeadlineTest,SetDeadlineWipesFlags)1348 TEST_F(HangWatchDeadlineTest, SetDeadlineWipesFlags) {
1349   auto [flags, deadline] = deadline_.GetFlagsAndDeadline();
1350 
1351   ASSERT_TRUE(deadline_.SetShouldBlockOnHang(flags, deadline));
1352   ASSERT_TRUE(deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1353 
1354   std::tie(flags, deadline) = deadline_.GetFlagsAndDeadline();
1355 
1356   deadline_.SetIgnoreCurrentWatchHangsInScope();
1357   ASSERT_TRUE(deadline_.IsFlagSet(
1358       HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1359 
1360   // Change the deadline.
1361   deadline_.SetDeadline(TimeTicks{});
1362   ASSERT_EQ(deadline_.GetDeadline(), TimeTicks{});
1363 
1364   // Verify the persistent flag stuck and the non-persistent one was unset.
1365   ASSERT_FALSE(
1366       deadline_.IsFlagSet(HangWatchDeadline::Flag::kShouldBlockOnHang));
1367   ASSERT_TRUE(deadline_.IsFlagSet(
1368       HangWatchDeadline::Flag::kIgnoreCurrentWatchHangsInScope));
1369 }
1370 
1371 }  // namespace internal
1372 
1373 }  // namespace base
1374