activity_tracker_unittest.cc 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/debug/activity_tracker.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/files/file.h"
  10. #include "base/files/file_util.h"
  11. #include "base/files/memory_mapped_file.h"
  12. #include "base/files/scoped_temp_dir.h"
  13. #include "base/memory/ptr_util.h"
  14. #include "base/memory/raw_ptr.h"
  15. #include "base/pending_task.h"
  16. #include "base/rand_util.h"
  17. #include "base/synchronization/condition_variable.h"
  18. #include "base/synchronization/lock.h"
  19. #include "base/test/spin_wait.h"
  20. #include "base/threading/platform_thread.h"
  21. #include "base/threading/simple_thread.h"
  22. #include "base/time/time.h"
  23. #include "testing/gtest/include/gtest/gtest.h"
  24. namespace base {
  25. namespace debug {
  26. namespace {
  27. class TestActivityTracker : public ThreadActivityTracker {
  28. public:
  29. TestActivityTracker(std::unique_ptr<char[]> memory, size_t mem_size)
  30. : ThreadActivityTracker(memset(memory.get(), 0, mem_size), mem_size),
  31. mem_segment_(std::move(memory)) {}
  32. ~TestActivityTracker() override = default;
  33. private:
  34. std::unique_ptr<char[]> mem_segment_;
  35. };
  36. } // namespace
  37. class ActivityTrackerTest : public testing::Test {
  38. public:
  39. const int kMemorySize = 1 << 20; // 1MiB
  40. const int kStackSize = 1 << 10; // 1KiB
  41. using ActivityId = ThreadActivityTracker::ActivityId;
  42. ActivityTrackerTest() = default;
  43. ~ActivityTrackerTest() override {
  44. GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
  45. if (global_tracker) {
  46. global_tracker->ReleaseTrackerForCurrentThreadForTesting();
  47. delete global_tracker;
  48. }
  49. }
  50. std::unique_ptr<ThreadActivityTracker> CreateActivityTracker() {
  51. std::unique_ptr<char[]> memory(new char[kStackSize]);
  52. return std::make_unique<TestActivityTracker>(std::move(memory), kStackSize);
  53. }
  54. size_t GetGlobalActiveTrackerCount() {
  55. GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
  56. if (!global_tracker)
  57. return 0;
  58. return global_tracker->thread_tracker_count_.load(
  59. std::memory_order_relaxed);
  60. }
  61. size_t GetGlobalInactiveTrackerCount() {
  62. GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
  63. if (!global_tracker)
  64. return 0;
  65. AutoLock autolock(global_tracker->thread_tracker_allocator_lock_);
  66. return global_tracker->thread_tracker_allocator_.cache_used();
  67. }
  68. size_t GetGlobalUserDataMemoryCacheUsed() {
  69. AutoLock autolock(GlobalActivityTracker::Get()->user_data_allocator_lock_);
  70. return GlobalActivityTracker::Get()->user_data_allocator_.cache_used();
  71. }
  72. void HandleProcessExit(ProcessId id,
  73. int64_t stamp,
  74. int code,
  75. GlobalActivityTracker::ProcessPhase phase,
  76. std::string&& command,
  77. ActivityUserData::Snapshot&& data) {
  78. exit_id_ = id;
  79. exit_stamp_ = stamp;
  80. exit_code_ = code;
  81. exit_phase_ = phase;
  82. exit_command_ = std::move(command);
  83. exit_data_ = std::move(data);
  84. }
  85. ProcessId exit_id_ = 0;
  86. int64_t exit_stamp_;
  87. int exit_code_;
  88. GlobalActivityTracker::ProcessPhase exit_phase_;
  89. std::string exit_command_;
  90. ActivityUserData::Snapshot exit_data_;
  91. };
  92. TEST_F(ActivityTrackerTest, UserDataTest) {
  93. char buffer[256];
  94. memset(buffer, 0, sizeof(buffer));
  95. ActivityUserData data(buffer, sizeof(buffer));
  96. size_t space = sizeof(buffer) - sizeof(ActivityUserData::MemoryHeader);
  97. ASSERT_EQ(space, data.available_);
  98. data.SetInt("foo", 1);
  99. space -= 24;
  100. ASSERT_EQ(space, data.available_);
  101. data.SetUint("b", 1U); // Small names fit beside header in a word.
  102. space -= 16;
  103. ASSERT_EQ(space, data.available_);
  104. data.Set("c", buffer, 10);
  105. space -= 24;
  106. ASSERT_EQ(space, data.available_);
  107. data.SetString("dear john", "it's been fun");
  108. space -= 32;
  109. ASSERT_EQ(space, data.available_);
  110. data.Set("c", buffer, 20);
  111. ASSERT_EQ(space, data.available_);
  112. data.SetString("dear john", "but we're done together");
  113. ASSERT_EQ(space, data.available_);
  114. data.SetString("dear john", "bye");
  115. ASSERT_EQ(space, data.available_);
  116. data.SetChar("d", 'x');
  117. space -= 8;
  118. ASSERT_EQ(space, data.available_);
  119. data.SetBool("ee", true);
  120. space -= 16;
  121. ASSERT_EQ(space, data.available_);
  122. data.SetString("f", "");
  123. space -= 8;
  124. ASSERT_EQ(space, data.available_);
  125. }
  126. TEST_F(ActivityTrackerTest, PushPopTest) {
  127. std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
  128. ThreadActivityTracker::Snapshot snapshot;
  129. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  130. ASSERT_EQ(0U, snapshot.activity_stack_depth);
  131. ASSERT_EQ(0U, snapshot.activity_stack.size());
  132. char origin1;
  133. ActivityId id1 = tracker->PushActivity(&origin1, Activity::ACT_TASK,
  134. ActivityData::ForTask(11));
  135. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  136. ASSERT_EQ(1U, snapshot.activity_stack_depth);
  137. ASSERT_EQ(1U, snapshot.activity_stack.size());
  138. EXPECT_NE(0, snapshot.activity_stack[0].time_internal);
  139. EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
  140. EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1),
  141. snapshot.activity_stack[0].origin_address);
  142. EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id);
  143. char origin2;
  144. char lock2;
  145. ActivityId id2 = tracker->PushActivity(&origin2, Activity::ACT_LOCK,
  146. ActivityData::ForLock(&lock2));
  147. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  148. ASSERT_EQ(2U, snapshot.activity_stack_depth);
  149. ASSERT_EQ(2U, snapshot.activity_stack.size());
  150. EXPECT_LE(snapshot.activity_stack[0].time_internal,
  151. snapshot.activity_stack[1].time_internal);
  152. EXPECT_EQ(Activity::ACT_LOCK, snapshot.activity_stack[1].activity_type);
  153. EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin2),
  154. snapshot.activity_stack[1].origin_address);
  155. EXPECT_EQ(reinterpret_cast<uintptr_t>(&lock2),
  156. snapshot.activity_stack[1].data.lock.lock_address);
  157. tracker->PopActivity(id2);
  158. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  159. ASSERT_EQ(1U, snapshot.activity_stack_depth);
  160. ASSERT_EQ(1U, snapshot.activity_stack.size());
  161. EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
  162. EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1),
  163. snapshot.activity_stack[0].origin_address);
  164. EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id);
  165. tracker->PopActivity(id1);
  166. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  167. ASSERT_EQ(0U, snapshot.activity_stack_depth);
  168. ASSERT_EQ(0U, snapshot.activity_stack.size());
  169. }
  170. TEST_F(ActivityTrackerTest, ScopedTaskTest) {
  171. GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
  172. ThreadActivityTracker* tracker =
  173. GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
  174. ThreadActivityTracker::Snapshot snapshot;
  175. ASSERT_EQ(0U, GetGlobalUserDataMemoryCacheUsed());
  176. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  177. ASSERT_EQ(0U, snapshot.activity_stack_depth);
  178. ASSERT_EQ(0U, snapshot.activity_stack.size());
  179. {
  180. PendingTask task1(FROM_HERE, DoNothing());
  181. ScopedTaskRunActivity activity1(task1);
  182. [[maybe_unused]] ActivityUserData& user_data1 = activity1.user_data();
  183. EXPECT_TRUE(activity1.IsRecorded());
  184. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  185. ASSERT_EQ(1U, snapshot.activity_stack_depth);
  186. ASSERT_EQ(1U, snapshot.activity_stack.size());
  187. EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
  188. {
  189. PendingTask task2(FROM_HERE, DoNothing());
  190. ScopedTaskRunActivity activity2(task2);
  191. [[maybe_unused]] ActivityUserData& user_data2 = activity2.user_data();
  192. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  193. ASSERT_EQ(2U, snapshot.activity_stack_depth);
  194. ASSERT_EQ(2U, snapshot.activity_stack.size());
  195. EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[1].activity_type);
  196. }
  197. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  198. ASSERT_EQ(1U, snapshot.activity_stack_depth);
  199. ASSERT_EQ(1U, snapshot.activity_stack.size());
  200. EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
  201. }
  202. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  203. ASSERT_EQ(0U, snapshot.activity_stack_depth);
  204. ASSERT_EQ(0U, snapshot.activity_stack.size());
  205. ASSERT_EQ(2U, GetGlobalUserDataMemoryCacheUsed());
  206. }
  207. namespace {
  208. class SimpleLockThread : public SimpleThread {
  209. public:
  210. SimpleLockThread(const std::string& name, Lock* lock)
  211. : SimpleThread(name, Options()),
  212. lock_(lock),
  213. data_changed_(false),
  214. is_running_(false) {}
  215. SimpleLockThread(const SimpleLockThread&) = delete;
  216. SimpleLockThread& operator=(const SimpleLockThread&) = delete;
  217. ~SimpleLockThread() override = default;
  218. void Run() override {
  219. ThreadActivityTracker* tracker =
  220. GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
  221. uint32_t pre_version = tracker->GetDataVersionForTesting();
  222. is_running_.store(true, std::memory_order_relaxed);
  223. lock_->Acquire();
  224. data_changed_ = tracker->GetDataVersionForTesting() != pre_version;
  225. lock_->Release();
  226. is_running_.store(false, std::memory_order_relaxed);
  227. }
  228. bool IsRunning() { return is_running_.load(std::memory_order_relaxed); }
  229. bool WasDataChanged() { return data_changed_; }
  230. private:
  231. raw_ptr<Lock> lock_;
  232. bool data_changed_;
  233. std::atomic<bool> is_running_;
  234. };
  235. } // namespace
  236. TEST_F(ActivityTrackerTest, LockTest) {
  237. GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
  238. ThreadActivityTracker* tracker =
  239. GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
  240. ThreadActivityTracker::Snapshot snapshot;
  241. ASSERT_EQ(0U, GetGlobalUserDataMemoryCacheUsed());
  242. Lock lock;
  243. uint32_t pre_version = tracker->GetDataVersionForTesting();
  244. // Check no activity when only "trying" a lock.
  245. EXPECT_TRUE(lock.Try());
  246. EXPECT_EQ(pre_version, tracker->GetDataVersionForTesting());
  247. lock.AssertAcquired();
  248. lock.Release();
  249. EXPECT_EQ(pre_version, tracker->GetDataVersionForTesting());
  250. // Check no activity when acquiring a free lock.
  251. SimpleLockThread t1("locker1", &lock);
  252. t1.Start();
  253. t1.Join();
  254. EXPECT_FALSE(t1.WasDataChanged());
  255. // Check that activity is recorded when acquring a busy lock.
  256. SimpleLockThread t2("locker2", &lock);
  257. lock.Acquire();
  258. t2.Start();
  259. while (!t2.IsRunning())
  260. PlatformThread::Sleep(Milliseconds(10));
  261. // t2 can't join until the lock is released but have to give time for t2 to
  262. // actually block on the lock before releasing it or the results will not
  263. // be correct.
  264. PlatformThread::Sleep(Milliseconds(200));
  265. lock.Release();
  266. // Now the results will be valid.
  267. t2.Join();
  268. EXPECT_TRUE(t2.WasDataChanged());
  269. }
  270. TEST_F(ActivityTrackerTest, ExceptionTest) {
  271. GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
  272. GlobalActivityTracker* global = GlobalActivityTracker::Get();
  273. ThreadActivityTracker* tracker =
  274. GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
  275. ThreadActivityTracker::Snapshot snapshot;
  276. ASSERT_EQ(0U, GetGlobalUserDataMemoryCacheUsed());
  277. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  278. ASSERT_EQ(0U, snapshot.last_exception.activity_type);
  279. char origin;
  280. global->RecordException(&origin, 42);
  281. ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
  282. EXPECT_EQ(Activity::ACT_EXCEPTION, snapshot.last_exception.activity_type);
  283. EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin),
  284. snapshot.last_exception.origin_address);
  285. EXPECT_EQ(42U, snapshot.last_exception.data.exception.code);
  286. }
  287. TEST_F(ActivityTrackerTest, CreateWithFileTest) {
  288. const char temp_name[] = "CreateWithFileTest";
  289. ScopedTempDir temp_dir;
  290. ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
  291. FilePath temp_file = temp_dir.GetPath().AppendASCII(temp_name);
  292. const size_t temp_size = 64 << 10; // 64 KiB
  293. // Create a global tracker on a new file.
  294. ASSERT_FALSE(PathExists(temp_file));
  295. GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "foo", 3);
  296. GlobalActivityTracker* global = GlobalActivityTracker::Get();
  297. EXPECT_EQ(std::string("foo"), global->allocator()->Name());
  298. global->ReleaseTrackerForCurrentThreadForTesting();
  299. delete global;
  300. // Create a global tracker over an existing file, replacing it. If the
  301. // replacement doesn't work, the name will remain as it was first created.
  302. ASSERT_TRUE(PathExists(temp_file));
  303. GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "bar", 3);
  304. global = GlobalActivityTracker::Get();
  305. EXPECT_EQ(std::string("bar"), global->allocator()->Name());
  306. global->ReleaseTrackerForCurrentThreadForTesting();
  307. delete global;
  308. }
  309. // GlobalActivityTracker tests below.
  310. TEST_F(ActivityTrackerTest, BasicTest) {
  311. GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
  312. GlobalActivityTracker* global = GlobalActivityTracker::Get();
  313. // Ensure the data repositories have backing store, indicated by non-zero ID.
  314. EXPECT_NE(0U, global->process_data().id());
  315. }
  316. namespace {
  317. class SimpleActivityThread : public SimpleThread {
  318. public:
  319. SimpleActivityThread(const std::string& name,
  320. const void* origin,
  321. Activity::Type activity,
  322. const ActivityData& data)
  323. : SimpleThread(name, Options()),
  324. origin_(origin),
  325. activity_(activity),
  326. data_(data),
  327. ready_(false),
  328. exit_(false),
  329. exit_condition_(&lock_) {}
  330. SimpleActivityThread(const SimpleActivityThread&) = delete;
  331. SimpleActivityThread& operator=(const SimpleActivityThread&) = delete;
  332. ~SimpleActivityThread() override = default;
  333. void Run() override {
  334. ThreadActivityTracker::ActivityId id =
  335. GlobalActivityTracker::Get()
  336. ->GetOrCreateTrackerForCurrentThread()
  337. ->PushActivity(origin_, activity_, data_);
  338. {
  339. AutoLock auto_lock(lock_);
  340. ready_.store(true, std::memory_order_release);
  341. while (!exit_.load(std::memory_order_relaxed))
  342. exit_condition_.Wait();
  343. }
  344. GlobalActivityTracker::Get()->GetTrackerForCurrentThread()->PopActivity(id);
  345. }
  346. void Exit() {
  347. AutoLock auto_lock(lock_);
  348. exit_.store(true, std::memory_order_relaxed);
  349. exit_condition_.Signal();
  350. }
  351. void WaitReady() {
  352. SPIN_FOR_1_SECOND_OR_UNTIL_TRUE(ready_.load(std::memory_order_acquire));
  353. }
  354. private:
  355. raw_ptr<const void> origin_;
  356. Activity::Type activity_;
  357. ActivityData data_;
  358. std::atomic<bool> ready_;
  359. std::atomic<bool> exit_;
  360. Lock lock_;
  361. ConditionVariable exit_condition_;
  362. };
  363. } // namespace
  364. TEST_F(ActivityTrackerTest, ThreadDeathTest) {
  365. GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
  366. GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
  367. const size_t starting_active = GetGlobalActiveTrackerCount();
  368. const size_t starting_inactive = GetGlobalInactiveTrackerCount();
  369. SimpleActivityThread t1("t1", nullptr, Activity::ACT_TASK,
  370. ActivityData::ForTask(11));
  371. t1.Start();
  372. t1.WaitReady();
  373. EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount());
  374. EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount());
  375. t1.Exit();
  376. t1.Join();
  377. EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount());
  378. EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
  379. // Start another thread and ensure it re-uses the existing memory.
  380. SimpleActivityThread t2("t2", nullptr, Activity::ACT_TASK,
  381. ActivityData::ForTask(22));
  382. t2.Start();
  383. t2.WaitReady();
  384. EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount());
  385. EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount());
  386. t2.Exit();
  387. t2.Join();
  388. EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount());
  389. EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
  390. }
  391. TEST_F(ActivityTrackerTest, ProcessDeathTest) {
  392. // This doesn't actually create and destroy a process. Instead, it uses for-
  393. // testing interfaces to simulate data created by other processes.
  394. const ProcessId other_process_id = GetCurrentProcId() + 1;
  395. GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
  396. GlobalActivityTracker* global = GlobalActivityTracker::Get();
  397. ThreadActivityTracker* thread = global->GetOrCreateTrackerForCurrentThread();
  398. // Get callbacks for process exit.
  399. global->SetProcessExitCallback(
  400. BindRepeating(&ActivityTrackerTest::HandleProcessExit, Unretained(this)));
  401. // Pretend than another process has started.
  402. global->RecordProcessLaunch(other_process_id, FILE_PATH_LITERAL("foo --bar"));
  403. // Do some activities.
  404. PendingTask task(FROM_HERE, DoNothing());
  405. ScopedTaskRunActivity activity(task);
  406. ActivityUserData& user_data = activity.user_data();
  407. ASSERT_NE(0U, user_data.id());
  408. // Get the memory-allocator references to that data.
  409. PersistentMemoryAllocator::Reference proc_data_ref =
  410. global->allocator()->GetAsReference(
  411. global->process_data().GetBaseAddress(),
  412. GlobalActivityTracker::kTypeIdProcessDataRecord);
  413. ASSERT_TRUE(proc_data_ref);
  414. PersistentMemoryAllocator::Reference tracker_ref =
  415. global->allocator()->GetAsReference(
  416. thread->GetBaseAddress(),
  417. GlobalActivityTracker::kTypeIdActivityTracker);
  418. ASSERT_TRUE(tracker_ref);
  419. PersistentMemoryAllocator::Reference user_data_ref =
  420. global->allocator()->GetAsReference(
  421. user_data.GetBaseAddress(),
  422. GlobalActivityTracker::kTypeIdUserDataRecord);
  423. ASSERT_TRUE(user_data_ref);
  424. // Make a copy of the thread-tracker state so it can be restored later.
  425. const size_t tracker_size = global->allocator()->GetAllocSize(tracker_ref);
  426. std::unique_ptr<char[]> tracker_copy(new char[tracker_size]);
  427. memcpy(tracker_copy.get(), thread->GetBaseAddress(), tracker_size);
  428. // Change the objects to appear to be owned by another process. Use a "past"
  429. // time so that exit-time is always later than create-time.
  430. const int64_t past_stamp = Time::Now().ToInternalValue() - 1;
  431. ProcessId owning_id;
  432. int64_t stamp;
  433. ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
  434. global->process_data().GetBaseAddress(), &owning_id, &stamp));
  435. EXPECT_NE(other_process_id, owning_id);
  436. ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
  437. thread->GetBaseAddress(), &owning_id, &stamp));
  438. EXPECT_NE(other_process_id, owning_id);
  439. ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
  440. &owning_id, &stamp));
  441. EXPECT_NE(other_process_id, owning_id);
  442. global->process_data().SetOwningProcessIdForTesting(other_process_id,
  443. past_stamp);
  444. thread->SetOwningProcessIdForTesting(other_process_id, past_stamp);
  445. user_data.SetOwningProcessIdForTesting(other_process_id, past_stamp);
  446. ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
  447. global->process_data().GetBaseAddress(), &owning_id, &stamp));
  448. EXPECT_EQ(other_process_id, owning_id);
  449. ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
  450. thread->GetBaseAddress(), &owning_id, &stamp));
  451. EXPECT_EQ(other_process_id, owning_id);
  452. ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
  453. &owning_id, &stamp));
  454. EXPECT_EQ(other_process_id, owning_id);
  455. // Check that process exit will perform callback and free the allocations.
  456. ASSERT_EQ(ProcessId{0}, exit_id_);
  457. ASSERT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecord,
  458. global->allocator()->GetType(proc_data_ref));
  459. ASSERT_EQ(GlobalActivityTracker::kTypeIdActivityTracker,
  460. global->allocator()->GetType(tracker_ref));
  461. ASSERT_EQ(GlobalActivityTracker::kTypeIdUserDataRecord,
  462. global->allocator()->GetType(user_data_ref));
  463. global->RecordProcessExit(other_process_id, 0);
  464. EXPECT_EQ(other_process_id, exit_id_);
  465. EXPECT_EQ("foo --bar", exit_command_);
  466. EXPECT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecordFree,
  467. global->allocator()->GetType(proc_data_ref));
  468. EXPECT_EQ(GlobalActivityTracker::kTypeIdActivityTrackerFree,
  469. global->allocator()->GetType(tracker_ref));
  470. EXPECT_EQ(GlobalActivityTracker::kTypeIdUserDataRecordFree,
  471. global->allocator()->GetType(user_data_ref));
  472. // Restore memory contents and types so things don't crash when doing real
  473. // process clean-up.
  474. memcpy(const_cast<void*>(thread->GetBaseAddress()), tracker_copy.get(),
  475. tracker_size);
  476. global->allocator()->ChangeType(
  477. proc_data_ref, GlobalActivityTracker::kTypeIdProcessDataRecord,
  478. GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
  479. global->allocator()->ChangeType(
  480. tracker_ref, GlobalActivityTracker::kTypeIdActivityTracker,
  481. GlobalActivityTracker::kTypeIdActivityTrackerFree, false);
  482. global->allocator()->ChangeType(
  483. user_data_ref, GlobalActivityTracker::kTypeIdUserDataRecord,
  484. GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
  485. }
  486. } // namespace debug
  487. } // namespace base