• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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/process/process.h"
6 
7 #include <memory>
8 #include <string>
9 #include <string_view>
10 #include <utility>
11 
12 #include "base/at_exit.h"
13 #include "base/debug/invalid_access_win.h"
14 #include "base/process/kill.h"
15 #include "base/test/multiprocess_test.h"
16 #include "base/test/test_timeouts.h"
17 #include "base/threading/platform_thread.h"
18 #include "base/threading/platform_thread_internal_posix.h"
19 #include "base/threading/thread_local.h"
20 #include "build/build_config.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "testing/multiprocess_func_list.h"
23 
24 #if BUILDFLAG(IS_CHROMEOS)
25 #include <sys/resource.h>
26 #include <unistd.h>
27 
28 #include <vector>
29 
30 #include "base/files/file_path.h"
31 #include "base/files/file_util.h"
32 #include "base/process/internal_linux.h"
33 #include "base/strings/string_number_conversions.h"
34 #include "base/strings/string_split.h"
35 #include "base/strings/string_util.h"
36 #include "base/strings/stringprintf.h"
37 #include "base/test/task_environment.h"
38 #include "base/time/time.h"
39 #endif  // BUILDFLAG(IS_CHROMEOS)
40 
41 #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
42 #include "base/test/scoped_feature_list.h"
43 #endif
44 
45 #if BUILDFLAG(IS_WIN)
46 #include <windows.h>
47 
48 #include "base/win/base_win_buildflags.h"
49 #include "base/win/windows_version.h"
50 #endif
51 
52 namespace {
53 
54 #if BUILDFLAG(IS_WIN)
55 constexpr int kExpectedStillRunningExitCode = 0x102;
56 #else
57 constexpr int kExpectedStillRunningExitCode = 0;
58 #endif
59 
60 constexpr int kDummyExitCode = 42;
61 
62 #if BUILDFLAG(IS_APPLE)
63 // Fake port provider that returns the calling process's
64 // task port, ignoring its argument.
65 class FakePortProvider : public base::PortProvider {
TaskForHandle(base::ProcessHandle process_handle) const66   mach_port_t TaskForHandle(base::ProcessHandle process_handle) const override {
67     return mach_task_self();
68   }
69 };
70 #endif
71 
72 #if BUILDFLAG(IS_CHROMEOS)
73 const char kForeground[] = "/chrome_renderers/foreground";
74 const char kCgroupRoot[] = "/sys/fs/cgroup/cpu";
75 const char kFullRendererCgroupRoot[] = "/sys/fs/cgroup/cpu/chrome_renderers";
76 const char kProcPath[] = "/proc/%d/cgroup";
77 
GetProcessCpuCgroup(const base::Process & process)78 std::string GetProcessCpuCgroup(const base::Process& process) {
79   std::string proc;
80   if (!base::ReadFileToString(
81           base::FilePath(base::StringPrintf(kProcPath, process.Pid())),
82           &proc)) {
83     return std::string();
84   }
85 
86   std::vector<std::string_view> lines = SplitStringPiece(
87       proc, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
88   for (const auto& line : lines) {
89     std::vector<std::string_view> fields = SplitStringPiece(
90         line, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
91     if (fields.size() != 3U) {
92       continue;
93     }
94 
95     if (fields[1] == "cpu") {
96       return static_cast<std::string>(fields[2]);
97     }
98   }
99 
100   return std::string();
101 }
102 
AddProcessToCpuCgroup(const base::Process & process,const std::string & cgroup)103 bool AddProcessToCpuCgroup(const base::Process& process,
104                            const std::string& cgroup) {
105   base::FilePath path(cgroup);
106   path = path.Append("cgroup.procs");
107   return base::WriteFile(path, base::NumberToString(process.Pid()));
108 }
109 #endif  // BUILDFLAG(IS_CHROMEOS)
110 
111 }  // namespace
112 
113 namespace base {
114 
115 class ProcessTest : public MultiProcessTest {
116 };
117 
TEST_F(ProcessTest,Create)118 TEST_F(ProcessTest, Create) {
119   Process process(SpawnChild("SimpleChildProcess"));
120   ASSERT_TRUE(process.IsValid());
121   ASSERT_FALSE(process.is_current());
122   EXPECT_NE(process.Pid(), kNullProcessId);
123   process.Close();
124   ASSERT_FALSE(process.IsValid());
125 }
126 
TEST_F(ProcessTest,CreateCurrent)127 TEST_F(ProcessTest, CreateCurrent) {
128   Process process = Process::Current();
129   ASSERT_TRUE(process.IsValid());
130   ASSERT_TRUE(process.is_current());
131   EXPECT_NE(process.Pid(), kNullProcessId);
132   process.Close();
133   ASSERT_FALSE(process.IsValid());
134 }
135 
TEST_F(ProcessTest,Move)136 TEST_F(ProcessTest, Move) {
137   Process process1(SpawnChild("SimpleChildProcess"));
138   EXPECT_TRUE(process1.IsValid());
139 
140   Process process2;
141   EXPECT_FALSE(process2.IsValid());
142 
143   process2 = std::move(process1);
144   EXPECT_TRUE(process2.IsValid());
145   EXPECT_FALSE(process1.IsValid());
146   EXPECT_FALSE(process2.is_current());
147 
148   Process process3 = Process::Current();
149   process2 = std::move(process3);
150   EXPECT_TRUE(process2.is_current());
151   EXPECT_TRUE(process2.IsValid());
152   EXPECT_FALSE(process3.IsValid());
153 }
154 
TEST_F(ProcessTest,Duplicate)155 TEST_F(ProcessTest, Duplicate) {
156   Process process1(SpawnChild("SimpleChildProcess"));
157   ASSERT_TRUE(process1.IsValid());
158 
159   Process process2 = process1.Duplicate();
160   ASSERT_TRUE(process1.IsValid());
161   ASSERT_TRUE(process2.IsValid());
162   EXPECT_EQ(process1.Pid(), process2.Pid());
163   EXPECT_FALSE(process1.is_current());
164   EXPECT_FALSE(process2.is_current());
165 
166   process1.Close();
167   ASSERT_TRUE(process2.IsValid());
168 }
169 
TEST_F(ProcessTest,DuplicateCurrent)170 TEST_F(ProcessTest, DuplicateCurrent) {
171   Process process1 = Process::Current();
172   ASSERT_TRUE(process1.IsValid());
173 
174   Process process2 = process1.Duplicate();
175   ASSERT_TRUE(process1.IsValid());
176   ASSERT_TRUE(process2.IsValid());
177   EXPECT_EQ(process1.Pid(), process2.Pid());
178   EXPECT_TRUE(process1.is_current());
179   EXPECT_TRUE(process2.is_current());
180 
181   process1.Close();
182   ASSERT_TRUE(process2.IsValid());
183 }
184 
MULTIPROCESS_TEST_MAIN(SleepyChildProcess)185 MULTIPROCESS_TEST_MAIN(SleepyChildProcess) {
186   PlatformThread::Sleep(TestTimeouts::action_max_timeout());
187   return 0;
188 }
189 
190 // TODO(crbug.com/42050607): Enable these tests on Fuchsia when
191 // CreationTime() is implemented.
TEST_F(ProcessTest,CreationTimeCurrentProcess)192 TEST_F(ProcessTest, CreationTimeCurrentProcess) {
193   // The current process creation time should be less than or equal to the
194   // current time.
195   EXPECT_FALSE(Process::Current().CreationTime().is_null());
196   EXPECT_LE(Process::Current().CreationTime(), Time::Now());
197 }
198 
199 #if !BUILDFLAG(IS_ANDROID)  // Cannot read other processes' creation time on
200                             // Android.
TEST_F(ProcessTest,CreationTimeOtherProcess)201 TEST_F(ProcessTest, CreationTimeOtherProcess) {
202   // The creation time of a process should be between a time recorded before it
203   // was spawned and a time recorded after it was spawned. However, since the
204   // base::Time and process creation clocks don't match, tolerate some error.
205   constexpr base::TimeDelta kTolerance =
206 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
207       // On Linux, process creation time is relative to boot time which has a
208       // 1-second resolution. Tolerate 1 second for the imprecise boot time and
209       // 100 ms for the imprecise clock.
210       Milliseconds(1100);
211 #elif BUILDFLAG(IS_WIN)
212       // On Windows, process creation time is based on the system clock while
213       // Time::Now() is a combination of system clock and
214       // QueryPerformanceCounter(). Tolerate 100 ms for the clock mismatch.
215       Milliseconds(100);
216 #elif BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_FUCHSIA)
217       // On Mac and Fuchsia, process creation time should be very precise.
218       Milliseconds(0);
219 #else
220 #error Unsupported platform
221 #endif
222   const Time before_creation = Time::Now();
223   Process process(SpawnChild("SleepyChildProcess"));
224   const Time after_creation = Time::Now();
225   const Time creation = process.CreationTime();
226   EXPECT_LE(before_creation - kTolerance, creation);
227   EXPECT_LE(creation, after_creation + kTolerance);
228   EXPECT_TRUE(process.Terminate(kDummyExitCode, true));
229 }
230 #endif  // !BUILDFLAG(IS_ANDROID)
231 
TEST_F(ProcessTest,Terminate)232 TEST_F(ProcessTest, Terminate) {
233   Process process(SpawnChild("SleepyChildProcess"));
234   ASSERT_TRUE(process.IsValid());
235 
236   int exit_code = kDummyExitCode;
237   EXPECT_EQ(TERMINATION_STATUS_STILL_RUNNING,
238             GetTerminationStatus(process.Handle(), &exit_code));
239   EXPECT_EQ(kExpectedStillRunningExitCode, exit_code);
240 
241   exit_code = kDummyExitCode;
242   int kExpectedExitCode = 250;
243   process.Terminate(kExpectedExitCode, false);
244   process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
245                                  &exit_code);
246 
247   EXPECT_NE(TERMINATION_STATUS_STILL_RUNNING,
248             GetTerminationStatus(process.Handle(), &exit_code));
249 #if BUILDFLAG(IS_WIN)
250   // Only Windows propagates the |exit_code| set in Terminate().
251   EXPECT_EQ(kExpectedExitCode, exit_code);
252 #endif
253 }
254 
AtExitHandler(void *)255 void AtExitHandler(void*) {
256   // At-exit handler should not be called at
257   // Process::TerminateCurrentProcessImmediately.
258   DCHECK(false);
259 }
260 
261 class ThreadLocalObject {
262  public:
~ThreadLocalObject()263   ~ThreadLocalObject() {
264     // Thread-local storage should not be destructed at
265     // Process::TerminateCurrentProcessImmediately.
266     DCHECK(false);
267   }
268 };
269 
MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode0)270 MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode0) {
271   base::ThreadLocalOwnedPointer<ThreadLocalObject> object;
272   object.Set(std::make_unique<ThreadLocalObject>());
273   base::AtExitManager::RegisterCallback(&AtExitHandler, nullptr);
274   Process::TerminateCurrentProcessImmediately(0);
275 }
276 
TEST_F(ProcessTest,TerminateCurrentProcessImmediatelyWithZeroExitCode)277 TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithZeroExitCode) {
278   Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode0"));
279   ASSERT_TRUE(process.IsValid());
280   int exit_code = 42;
281   ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
282                                              &exit_code));
283   EXPECT_EQ(0, exit_code);
284 }
285 
MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode250)286 MULTIPROCESS_TEST_MAIN(TerminateCurrentProcessImmediatelyWithCode250) {
287   Process::TerminateCurrentProcessImmediately(250);
288 }
289 
TEST_F(ProcessTest,TerminateCurrentProcessImmediatelyWithNonZeroExitCode)290 TEST_F(ProcessTest, TerminateCurrentProcessImmediatelyWithNonZeroExitCode) {
291   Process process(SpawnChild("TerminateCurrentProcessImmediatelyWithCode250"));
292   ASSERT_TRUE(process.IsValid());
293   int exit_code = 42;
294   ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
295                                              &exit_code));
296   EXPECT_EQ(250, exit_code);
297 }
298 
MULTIPROCESS_TEST_MAIN(FastSleepyChildProcess)299 MULTIPROCESS_TEST_MAIN(FastSleepyChildProcess) {
300   PlatformThread::Sleep(TestTimeouts::tiny_timeout() * 10);
301   return 0;
302 }
303 
TEST_F(ProcessTest,WaitForExit)304 TEST_F(ProcessTest, WaitForExit) {
305   Process process(SpawnChild("FastSleepyChildProcess"));
306   ASSERT_TRUE(process.IsValid());
307 
308   int exit_code = kDummyExitCode;
309   EXPECT_TRUE(process.WaitForExit(&exit_code));
310   EXPECT_EQ(0, exit_code);
311 }
312 
TEST_F(ProcessTest,WaitForExitWithTimeout)313 TEST_F(ProcessTest, WaitForExitWithTimeout) {
314   Process process(SpawnChild("SleepyChildProcess"));
315   ASSERT_TRUE(process.IsValid());
316 
317   int exit_code = kDummyExitCode;
318   TimeDelta timeout = TestTimeouts::tiny_timeout();
319   EXPECT_FALSE(process.WaitForExitWithTimeout(timeout, &exit_code));
320   EXPECT_EQ(kDummyExitCode, exit_code);
321 
322   process.Terminate(kDummyExitCode, false);
323 }
324 
325 #if BUILDFLAG(IS_WIN)
TEST_F(ProcessTest,WaitForExitOrEventWithProcessExit)326 TEST_F(ProcessTest, WaitForExitOrEventWithProcessExit) {
327   Process process(SpawnChild("FastSleepyChildProcess"));
328   ASSERT_TRUE(process.IsValid());
329 
330   base::win::ScopedHandle stop_watching_handle(
331       CreateEvent(nullptr, TRUE, FALSE, nullptr));
332 
333   int exit_code = kDummyExitCode;
334   EXPECT_EQ(process.WaitForExitOrEvent(stop_watching_handle, &exit_code),
335             base::Process::WaitExitStatus::PROCESS_EXITED);
336   EXPECT_EQ(0, exit_code);
337 }
338 
TEST_F(ProcessTest,WaitForExitOrEventWithEventSet)339 TEST_F(ProcessTest, WaitForExitOrEventWithEventSet) {
340   Process process(SpawnChild("SleepyChildProcess"));
341   ASSERT_TRUE(process.IsValid());
342 
343   base::win::ScopedHandle stop_watching_handle(
344       CreateEvent(nullptr, TRUE, TRUE, nullptr));
345 
346   int exit_code = kDummyExitCode;
347   EXPECT_EQ(process.WaitForExitOrEvent(stop_watching_handle, &exit_code),
348             base::Process::WaitExitStatus::STOP_EVENT_SIGNALED);
349   EXPECT_EQ(kDummyExitCode, exit_code);
350 
351   process.Terminate(kDummyExitCode, false);
352 }
353 #endif  // BUILDFLAG(IS_WIN)
354 
355 // Ensure that the priority of a process is restored correctly after
356 // backgrounding and restoring.
357 // Note: a platform may not be willing or able to lower the priority of
358 // a process. The calls to SetProcessPriority should be noops then.
TEST_F(ProcessTest,SetProcessPriority)359 TEST_F(ProcessTest, SetProcessPriority) {
360   if (!Process::CanSetPriority()) {
361     return;
362   }
363   Process process(SpawnChild("SimpleChildProcess"));
364   int old_os_priority = process.GetOSPriority();
365 #if BUILDFLAG(IS_APPLE)
366   // On the Mac, backgrounding a process requires a port to that process.
367   // In the browser it's available through the MachBroker class, which is not
368   // part of base. Additionally, there is an indefinite amount of time between
369   // spawning a process and receiving its port. Because this test just checks
370   // the ability to background/foreground a process, we can use the current
371   // process's port instead.
372   FakePortProvider provider;
373   EXPECT_TRUE(process.SetPriority(&provider, Process::Priority::kBestEffort));
374   EXPECT_EQ(process.GetPriority(&provider), Process::Priority::kBestEffort);
375   EXPECT_TRUE(process.SetPriority(&provider, Process::Priority::kUserBlocking));
376   EXPECT_EQ(process.GetPriority(&provider), Process::Priority::kUserBlocking);
377 
378 #else
379   EXPECT_TRUE(process.SetPriority(base::Process::Priority::kBestEffort));
380   EXPECT_EQ(process.GetPriority(), Process::Priority::kBestEffort);
381   EXPECT_TRUE(process.SetPriority(base::Process::Priority::kUserBlocking));
382   EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
383 #endif
384 
385 #if BUILDFLAG(IS_WIN)
386   EXPECT_TRUE(process.SetPriority(base::Process::Priority::kUserVisible));
387   // Eco QoS level read & write are not supported prior to WIN11_22H2,
388   // Priority::kUserVisible has same behavior as Priority::kUserBlocking, and
389   // is translated as Priority::kUserBlocking.
390   if (base::win::OSInfo::GetInstance()->version() >=
391       base::win::Version::WIN11_22H2) {
392     EXPECT_EQ(process.GetPriority(), Process::Priority::kUserVisible);
393   } else {
394     EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
395   }
396 
397   EXPECT_TRUE(process.SetPriority(base::Process::Priority::kBestEffort));
398   EXPECT_EQ(process.GetPriority(), Process::Priority::kBestEffort);
399   EXPECT_TRUE(process.SetPriority(base::Process::Priority::kUserVisible));
400   if (base::win::OSInfo::GetInstance()->version() >=
401       base::win::Version::WIN11_22H2) {
402     EXPECT_EQ(process.GetPriority(), Process::Priority::kUserVisible);
403   } else {
404     EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
405   }
406   EXPECT_TRUE(process.SetPriority(base::Process::Priority::kUserBlocking));
407   EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
408 #elif !BUILDFLAG(IS_APPLE)
409   // On other platforms, Process::Priority::kUserVisible is translated as
410   // Process::Priority::kUserBlocking.
411   EXPECT_TRUE(process.SetPriority(base::Process::Priority::kUserVisible));
412   EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
413 #endif
414 
415   int new_os_priority = process.GetOSPriority();
416   EXPECT_EQ(old_os_priority, new_os_priority);
417 }
418 
419 #if BUILDFLAG(IS_CHROMEOS)
IsThreadRT(PlatformThreadId thread_id)420 bool IsThreadRT(PlatformThreadId thread_id) {
421   // Check if the thread is running in real-time mode
422   int sched = sched_getscheduler(
423       PlatformThread::CurrentId() == thread_id ? 0 : thread_id);
424   if (sched == -1) {
425     // The thread may disappear for any reason so ignore ESRCH.
426     DPLOG_IF(ERROR, errno != ESRCH)
427         << "Failed to call sched_getscheduler on thread_id=" << thread_id;
428     return false;
429   }
430   return sched == SCHED_RR || sched == SCHED_FIFO;
431 }
432 
433 // Verify that all the threads in a process are RT or not.
AssertThreadsRT(int process_id,bool is_rt)434 void AssertThreadsRT(int process_id, bool is_rt) {
435   internal::ForEachProcessTask(
436       process_id, [is_rt](PlatformThreadId tid, const FilePath& /* path */) {
437         EXPECT_EQ(IsThreadRT(tid), is_rt);
438       });
439 }
440 
AssertThreadsType(int process_id,ThreadType type)441 void AssertThreadsType(int process_id, ThreadType type) {
442   internal::ForEachProcessTask(process_id, [process_id, type](
443                                                PlatformThreadId tid,
444                                                const FilePath& path) {
445     EXPECT_EQ(PlatformThread::GetThreadTypeFromThreadId(process_id, tid), type);
446   });
447 }
448 
AssertThreadsBgState(int process_id,bool is_bg)449 void AssertThreadsBgState(int process_id, bool is_bg) {
450   internal::ForEachProcessTask(
451       process_id, [is_bg](PlatformThreadId tid, const FilePath& path) {
452         EXPECT_EQ(PlatformThreadLinux::IsThreadBackgroundedForTest(tid), is_bg);
453       });
454 }
455 
456 namespace {
457 
458 class FunctionTestThread : public PlatformThread::Delegate {
459  public:
460   FunctionTestThread() = default;
461 
462   FunctionTestThread(const FunctionTestThread&) = delete;
463   FunctionTestThread& operator=(const FunctionTestThread&) = delete;
464 
ThreadMain()465   void ThreadMain() override {
466     PlatformThread::SetCurrentThreadType(ThreadType::kDisplayCritical);
467     while (true) {
468       PlatformThread::Sleep(Milliseconds(100));
469     }
470   }
471 };
472 
473 class RTAudioFunctionTestThread : public PlatformThread::Delegate {
474  public:
475   RTAudioFunctionTestThread() = default;
476 
477   RTAudioFunctionTestThread(const RTAudioFunctionTestThread&) = delete;
478   RTAudioFunctionTestThread& operator=(const RTAudioFunctionTestThread&) =
479       delete;
480 
ThreadMain()481   void ThreadMain() override {
482     PlatformThread::SetCurrentThreadType(ThreadType::kRealtimeAudio);
483     while (true) {
484       PlatformThread::Sleep(Milliseconds(100));
485     }
486   }
487 };
488 
489 class RTDisplayFunctionTestThread : public PlatformThread::Delegate {
490  public:
491   RTDisplayFunctionTestThread() = default;
492 
493   RTDisplayFunctionTestThread(const RTDisplayFunctionTestThread&) = delete;
494   RTDisplayFunctionTestThread& operator=(const RTDisplayFunctionTestThread&) =
495       delete;
496 
ThreadMain()497   void ThreadMain() override {
498     PlatformThread::SetCurrentThreadType(ThreadType::kDisplayCritical);
499     while (true) {
500       PlatformThread::Sleep(Milliseconds(100));
501     }
502   }
503 };
504 
505 int create_threads_after_bg;
506 bool bg_threads_created;
507 bool prebg_threads_created;
508 bool audio_rt_threads_created;
509 bool display_rt_threads_created;
510 
sig_create_threads_after_bg(int signum)511 void sig_create_threads_after_bg(int signum) {
512   if (signum == SIGUSR1) {
513     create_threads_after_bg = true;
514   }
515 }
516 
sig_prebg_threads_created_handler(int signum)517 void sig_prebg_threads_created_handler(int signum) {
518   if (signum == SIGUSR1) {
519     prebg_threads_created = true;
520   }
521 }
522 
sig_bg_threads_created_handler(int signum)523 void sig_bg_threads_created_handler(int signum) {
524   if (signum == SIGUSR2) {
525     bg_threads_created = true;
526   }
527 }
528 
sig_audio_rt_threads_created_handler(int signum)529 void sig_audio_rt_threads_created_handler(int signum) {
530   if (signum == SIGUSR1) {
531     audio_rt_threads_created = true;
532   }
533 }
534 
sig_display_rt_threads_created_handler(int signum)535 void sig_display_rt_threads_created_handler(int signum) {
536   if (signum == SIGUSR1) {
537     display_rt_threads_created = true;
538   }
539 }
540 
541 }  // namespace
542 
MULTIPROCESS_TEST_MAIN(ProcessThreadBackgroundingMain)543 MULTIPROCESS_TEST_MAIN(ProcessThreadBackgroundingMain) {
544   PlatformThreadHandle handle1, handle2, handle3;
545   FunctionTestThread thread1, thread2, thread3;
546   base::test::ScopedFeatureList scoped_feature_list(kSetThreadBgForBgProcess);
547   PlatformThreadChromeOS::InitializeFeatures();
548   PlatformThread::SetCurrentThreadType(ThreadType::kDisplayCritical);
549 
550   // Register signal handler to be notified to create threads after backgrounding.
551   signal(SIGUSR1, sig_create_threads_after_bg);
552 
553   if (!PlatformThread::Create(0, &thread1, &handle1)) {
554     ADD_FAILURE() << "ProcessThreadBackgroundingMain: Failed to create thread1";
555     return 1;
556   }
557 
558   if (!PlatformThread::Create(0, &thread2, &handle2)) {
559     ADD_FAILURE() << "ProcessThreadBackgroundingMain: Failed to create thread2";
560     return 1;
561   }
562 
563   // Signal that the pre-backgrounding threads were created.
564   kill(getppid(), SIGUSR1);
565 
566   // Wait for the signal to background.
567   while (create_threads_after_bg == 0) {
568     PlatformThread::Sleep(Milliseconds(100));
569   }
570 
571   // Test creation of thread while process is backgrounded.
572   if (!PlatformThread::Create(0, &thread3, &handle3)) {
573     ADD_FAILURE() << "ProcessThreadBackgroundingMain: Failed to create thread3";
574     return 1;
575   }
576 
577   // Signal that the thread after backgrounding was created.
578   kill(getppid(), SIGUSR2);
579 
580   while (true) {
581     PlatformThread::Sleep(Milliseconds(100));
582   }
583 }
584 
585 // ProcessThreadBackgrounding: A test to create a process and verify
586 // that the threads in the process are backgrounded correctly.
TEST_F(ProcessTest,ProcessThreadBackgrounding)587 TEST_F(ProcessTest, ProcessThreadBackgrounding) {
588   if (!PlatformThread::CanChangeThreadType(ThreadType::kDefault,
589                                            ThreadType::kDisplayCritical)) {
590     return;
591   }
592 
593   base::test::ScopedFeatureList scoped_feature_list(kSetThreadBgForBgProcess);
594   PlatformThreadChromeOS::InitializeFeatures();
595 
596   // Register signal handlers to be notified of events in child process.
597   signal(SIGUSR1, sig_prebg_threads_created_handler);
598   signal(SIGUSR2, sig_bg_threads_created_handler);
599 
600   Process process(SpawnChild("ProcessThreadBackgroundingMain"));
601   EXPECT_TRUE(process.IsValid());
602 
603   // Wait for the signal that the initial pre-backgrounding
604   // threads were created.
605   while (!prebg_threads_created) {
606     PlatformThread::Sleep(Milliseconds(100));
607   }
608 
609   // Verify that the threads are initially in the foreground.
610   AssertThreadsType(process.Pid(), ThreadType::kDisplayCritical);
611   AssertThreadsBgState(process.Pid(), false);
612 
613   EXPECT_TRUE(process.SetPriority(Process::Priority::kBestEffort));
614 
615   // Send a signal to create a thread while the process is backgrounded.
616   kill(process.Pid(), SIGUSR1);
617 
618   // Wait for the signal that backgrounding completed
619   while (!bg_threads_created) {
620     PlatformThread::Sleep(Milliseconds(100));
621   }
622 
623   // Verify that the threads are backgrounded.
624   AssertThreadsType(process.Pid(), ThreadType::kDisplayCritical);
625   AssertThreadsBgState(process.Pid(), true);
626 
627   EXPECT_TRUE(process.SetPriority(Process::Priority::kUserBlocking));
628   EXPECT_TRUE(process.GetPriority() == base::Process::Priority::kUserBlocking);
629 
630   // Verify that the threads are foregrounded.
631   AssertThreadsType(process.Pid(), ThreadType::kDisplayCritical);
632   AssertThreadsBgState(process.Pid(), false);
633 }
634 
MULTIPROCESS_TEST_MAIN(ProcessRTAudioBgMain)635 MULTIPROCESS_TEST_MAIN(ProcessRTAudioBgMain) {
636   PlatformThreadHandle handle1;
637   RTAudioFunctionTestThread thread1;
638   base::test::ScopedFeatureList scoped_feature_list(kSetThreadBgForBgProcess);
639   PlatformThreadChromeOS::InitializeFeatures();
640   PlatformThread::SetCurrentThreadType(ThreadType::kRealtimeAudio);
641 
642   if (!PlatformThread::Create(0, &thread1, &handle1)) {
643     ADD_FAILURE() << "ProcessRTAudioBgMain: Failed to create thread1";
644     return 1;
645   }
646 
647   // Signal that the RT thread was created.
648   kill(getppid(), SIGUSR1);
649 
650   while (true) {
651     PlatformThread::Sleep(Milliseconds(100));
652   }
653 }
654 
655 // Test the property of kRealTimeAudio threads in a backgrounded process.
TEST_F(ProcessTest,ProcessRTAudioBg)656 TEST_F(ProcessTest, ProcessRTAudioBg) {
657   if (!PlatformThread::CanChangeThreadType(ThreadType::kDefault,
658                                            ThreadType::kDisplayCritical)) {
659     return;
660   }
661 
662   base::test::ScopedFeatureList scoped_feature_list(kSetThreadBgForBgProcess);
663   PlatformThreadChromeOS::InitializeFeatures();
664 
665   // Register signal handler to check if RT thread was created by child process.
666   signal(SIGUSR1, sig_audio_rt_threads_created_handler);
667 
668   Process process(SpawnChild("ProcessRTAudioBgMain"));
669   EXPECT_TRUE(process.IsValid());
670 
671   // Wait for signal that threads were spawned
672   while (!audio_rt_threads_created) {
673     PlatformThread::Sleep(Milliseconds(100));
674   }
675 
676   AssertThreadsRT(process.Pid(), true);
677   AssertThreadsType(process.Pid(), ThreadType::kRealtimeAudio);
678   AssertThreadsBgState(process.Pid(), false);
679 
680   EXPECT_TRUE(process.SetPriority(Process::Priority::kBestEffort));
681   EXPECT_TRUE(process.GetPriority() == base::Process::Priority::kBestEffort);
682 
683   // Verify that nothing changed when process is kBestEffort
684   AssertThreadsRT(process.Pid(), true);
685   AssertThreadsType(process.Pid(), ThreadType::kRealtimeAudio);
686   AssertThreadsBgState(process.Pid(), false);
687 
688   EXPECT_TRUE(process.SetPriority(Process::Priority::kUserBlocking));
689   EXPECT_TRUE(process.GetPriority() == base::Process::Priority::kUserBlocking);
690 
691   // Verify that nothing changed when process is kUserBlocking
692   AssertThreadsRT(process.Pid(), true);
693   AssertThreadsType(process.Pid(), ThreadType::kRealtimeAudio);
694   AssertThreadsBgState(process.Pid(), false);
695 }
696 
MULTIPROCESS_TEST_MAIN(ProcessRTDisplayBgMain)697 MULTIPROCESS_TEST_MAIN(ProcessRTDisplayBgMain) {
698   PlatformThreadHandle handle1;
699   RTDisplayFunctionTestThread thread1;
700   base::test::ScopedFeatureList scoped_feature_list;
701   scoped_feature_list.InitWithFeatures(
702       {kSetThreadBgForBgProcess, kSetRtForDisplayThreads}, {});
703   PlatformThreadChromeOS::InitializeFeatures();
704 
705   PlatformThread::SetCurrentThreadType(ThreadType::kDisplayCritical);
706 
707   if (!PlatformThread::Create(0, &thread1, &handle1)) {
708     ADD_FAILURE() << "ProcessRTDisplayBgMain: Failed to create thread1";
709     return 1;
710   }
711 
712   // Signal that the RT thread was created.
713   kill(getppid(), SIGUSR1);
714 
715   while (true) {
716     PlatformThread::Sleep(Milliseconds(100));
717   }
718 }
719 
720 // Test the property of kDisplayCritical threads in a backgrounded process.
TEST_F(ProcessTest,ProcessRTDisplayBg)721 TEST_F(ProcessTest, ProcessRTDisplayBg) {
722   if (!PlatformThread::CanChangeThreadType(ThreadType::kDefault,
723                                            ThreadType::kDisplayCritical)) {
724     return;
725   }
726 
727   base::test::ScopedFeatureList scoped_feature_list;
728   scoped_feature_list.InitWithFeatures(
729       {kSetThreadBgForBgProcess, kSetRtForDisplayThreads}, {});
730   PlatformThreadChromeOS::InitializeFeatures();
731 
732   // Register signal handler to check if RT thread was created by child process.
733   signal(SIGUSR1, sig_display_rt_threads_created_handler);
734 
735   Process process(SpawnChild("ProcessRTDisplayBgMain"));
736   EXPECT_TRUE(process.IsValid());
737 
738   // Wait for signal that threads were spawned
739   while (!display_rt_threads_created) {
740     PlatformThread::Sleep(Milliseconds(100));
741   }
742 
743   AssertThreadsRT(process.Pid(), true);
744   AssertThreadsType(process.Pid(), ThreadType::kDisplayCritical);
745   AssertThreadsBgState(process.Pid(), false);
746 
747   EXPECT_TRUE(process.SetPriority(Process::Priority::kBestEffort));
748   EXPECT_TRUE(process.GetPriority() == base::Process::Priority::kBestEffort);
749 
750   // Verify that the threads transitioned away from RT when process is
751   // kBestEffort
752   AssertThreadsRT(process.Pid(), false);
753   AssertThreadsType(process.Pid(), ThreadType::kDisplayCritical);
754   AssertThreadsBgState(process.Pid(), true);
755 
756   EXPECT_TRUE(process.SetPriority(Process::Priority::kUserBlocking));
757   EXPECT_TRUE(process.GetPriority() == base::Process::Priority::kUserBlocking);
758 
759   // Verify that it is back to RT when process is kUserBlocking
760   AssertThreadsRT(process.Pid(), true);
761   AssertThreadsType(process.Pid(), ThreadType::kDisplayCritical);
762   AssertThreadsBgState(process.Pid(), false);
763 }
764 
765 #endif  // BUILDFLAG(IS_CHROMEOS)
766 
767 // Consumers can use WaitForExitWithTimeout(base::TimeDelta(), nullptr) to check
768 // whether the process is still running. This may not be safe because of the
769 // potential reusing of the process id. So we won't export Process::IsRunning()
770 // on all platforms. But for the controllable scenario in the test cases, the
771 // behavior should be guaranteed.
TEST_F(ProcessTest,CurrentProcessIsRunning)772 TEST_F(ProcessTest, CurrentProcessIsRunning) {
773   EXPECT_FALSE(Process::Current().WaitForExitWithTimeout(
774       base::TimeDelta(), nullptr));
775 }
776 
777 #if BUILDFLAG(IS_APPLE)
778 // On Mac OSX, we can detect whether a non-child process is running.
TEST_F(ProcessTest,PredefinedProcessIsRunning)779 TEST_F(ProcessTest, PredefinedProcessIsRunning) {
780   // Process 1 is the /sbin/launchd, it should be always running.
781   EXPECT_FALSE(Process::Open(1).WaitForExitWithTimeout(
782       base::TimeDelta(), nullptr));
783 }
784 #endif
785 
786 // Test is disabled on Windows AMR64 because
787 // TerminateWithHeapCorruption() isn't expected to work there.
788 // See: https://crbug.com/1054423
789 #if BUILDFLAG(IS_WIN)
790 #if defined(ARCH_CPU_ARM64)
791 #define MAYBE_HeapCorruption DISABLED_HeapCorruption
792 #else
793 #define MAYBE_HeapCorruption HeapCorruption
794 #endif
TEST_F(ProcessTest,MAYBE_HeapCorruption)795 TEST_F(ProcessTest, MAYBE_HeapCorruption) {
796   EXPECT_EXIT(base::debug::win::TerminateWithHeapCorruption(),
797               ::testing::ExitedWithCode(STATUS_HEAP_CORRUPTION), "");
798 }
799 
800 #if BUILDFLAG(WIN_ENABLE_CFG_GUARDS)
801 #define MAYBE_ControlFlowViolation ControlFlowViolation
802 #else
803 #define MAYBE_ControlFlowViolation DISABLED_ControlFlowViolation
804 #endif
TEST_F(ProcessTest,MAYBE_ControlFlowViolation)805 TEST_F(ProcessTest, MAYBE_ControlFlowViolation) {
806   // CFG causes ntdll!RtlFailFast2 to be called resulting in uncatchable
807   // 0xC0000409 (STATUS_STACK_BUFFER_OVERRUN) exception.
808   EXPECT_EXIT(base::debug::win::TerminateWithControlFlowViolation(),
809               ::testing::ExitedWithCode(STATUS_STACK_BUFFER_OVERRUN), "");
810 }
811 
812 #endif  // BUILDFLAG(IS_WIN)
813 
TEST_F(ProcessTest,ChildProcessIsRunning)814 TEST_F(ProcessTest, ChildProcessIsRunning) {
815   Process process(SpawnChild("SleepyChildProcess"));
816   EXPECT_FALSE(process.WaitForExitWithTimeout(
817       base::TimeDelta(), nullptr));
818   process.Terminate(0, true);
819   EXPECT_TRUE(process.WaitForExitWithTimeout(
820       base::TimeDelta(), nullptr));
821 }
822 
823 #if BUILDFLAG(IS_CHROMEOS)
824 
825 // Tests that the function GetProcessPriorityCGroup() can parse the contents
826 // of the /proc/<pid>/cgroup file successfully.
TEST_F(ProcessTest,TestGetProcessPriorityCGroup)827 TEST_F(ProcessTest, TestGetProcessPriorityCGroup) {
828   const char kNotBackgroundedCGroup[] = "5:cpuacct,cpu,cpuset:/daemons\n";
829   const char kBackgroundedCGroup[] =
830       "2:freezer:/chrome_renderers/to_be_frozen\n"
831       "1:cpu:/chrome_renderers/background\n";
832 
833   EXPECT_EQ(GetProcessPriorityCGroup(kNotBackgroundedCGroup),
834             Process::Priority::kUserBlocking);
835   EXPECT_EQ(GetProcessPriorityCGroup(kBackgroundedCGroup),
836             Process::Priority::kBestEffort);
837 }
838 
TEST_F(ProcessTest,InitializePriorityEmptyProcess)839 TEST_F(ProcessTest, InitializePriorityEmptyProcess) {
840   // TODO(b/172213843): base::Process is used by base::TestSuite::Initialize
841   // before we can use ScopedFeatureList here. Update the test to allow the
842   // use of ScopedFeatureList before base::TestSuite::Initialize runs.
843   if (!Process::OneGroupPerRendererEnabledForTesting())
844     return;
845 
846   Process process;
847   process.InitializePriority();
848   const std::string unique_token = process.unique_token();
849   ASSERT_TRUE(unique_token.empty());
850 }
851 
TEST_F(ProcessTest,SetProcessBackgroundedOneCgroupPerRender)852 TEST_F(ProcessTest, SetProcessBackgroundedOneCgroupPerRender) {
853   if (!Process::OneGroupPerRendererEnabledForTesting())
854     return;
855 
856   base::test::TaskEnvironment task_env;
857 
858   Process process(SpawnChild("SimpleChildProcess"));
859   process.InitializePriority();
860   const std::string unique_token = process.unique_token();
861   ASSERT_FALSE(unique_token.empty());
862 
863   EXPECT_TRUE(process.SetPriority(Process::Priority::kUserBlocking));
864   EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
865   std::string cgroup = GetProcessCpuCgroup(process);
866   EXPECT_FALSE(cgroup.empty());
867   EXPECT_NE(cgroup.find(unique_token), std::string::npos);
868 
869   EXPECT_TRUE(process.SetPriority(Process::Priority::kBestEffort));
870   EXPECT_EQ(process.GetPriority(), Process::Priority::kBestEffort);
871 
872   EXPECT_TRUE(process.Terminate(0, false));
873   // Terminate should post a task, wait for it to run
874   task_env.RunUntilIdle();
875 
876   cgroup = std::string(kCgroupRoot) + cgroup;
877   EXPECT_FALSE(base::DirectoryExists(FilePath(cgroup)));
878 }
879 
TEST_F(ProcessTest,CleanUpBusyProcess)880 TEST_F(ProcessTest, CleanUpBusyProcess) {
881   if (!Process::OneGroupPerRendererEnabledForTesting())
882     return;
883 
884   base::test::TaskEnvironment task_env;
885 
886   Process process(SpawnChild("SimpleChildProcess"));
887   process.InitializePriority();
888   const std::string unique_token = process.unique_token();
889   ASSERT_FALSE(unique_token.empty());
890 
891   EXPECT_TRUE(process.SetPriority(Process::Priority::kUserBlocking));
892   EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
893   std::string cgroup = GetProcessCpuCgroup(process);
894   EXPECT_FALSE(cgroup.empty());
895   EXPECT_NE(cgroup.find(unique_token), std::string::npos);
896 
897   // Add another process to the cgroup to ensure it stays busy.
898   cgroup = std::string(kCgroupRoot) + cgroup;
899   Process process2(SpawnChild("SimpleChildProcess"));
900   EXPECT_TRUE(AddProcessToCpuCgroup(process2, cgroup));
901 
902   // Terminate the first process that should tirgger a cleanup of the cgroup
903   EXPECT_TRUE(process.Terminate(0, false));
904   // Wait until the background task runs once. This should fail and requeue
905   // another task to retry.
906   task_env.RunUntilIdle();
907   EXPECT_TRUE(base::DirectoryExists(FilePath(cgroup)));
908 
909   // Move the second process to free the cgroup
910   std::string foreground_path =
911       std::string(kCgroupRoot) + std::string(kForeground);
912   EXPECT_TRUE(AddProcessToCpuCgroup(process2, foreground_path));
913 
914   // Wait for the retry.
915   PlatformThread::Sleep(base::Milliseconds(1100));
916   task_env.RunUntilIdle();
917   // The cgroup should be deleted now.
918   EXPECT_FALSE(base::DirectoryExists(FilePath(cgroup)));
919 
920   process2.Terminate(0, false);
921 }
922 
TEST_F(ProcessTest,SetProcessBackgroundedEmptyToken)923 TEST_F(ProcessTest, SetProcessBackgroundedEmptyToken) {
924   if (!Process::OneGroupPerRendererEnabledForTesting())
925     return;
926 
927   Process process(SpawnChild("SimpleChildProcess"));
928   const std::string unique_token = process.unique_token();
929   ASSERT_TRUE(unique_token.empty());
930 
931   // Moving to the foreground should use the default foreground path.
932   EXPECT_TRUE(process.SetPriority(Process::Priority::kUserBlocking));
933   EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
934   std::string cgroup = GetProcessCpuCgroup(process);
935   EXPECT_FALSE(cgroup.empty());
936   EXPECT_EQ(cgroup, kForeground);
937 }
938 
TEST_F(ProcessTest,CleansUpStaleGroups)939 TEST_F(ProcessTest, CleansUpStaleGroups) {
940   if (!Process::OneGroupPerRendererEnabledForTesting())
941     return;
942 
943   base::test::TaskEnvironment task_env;
944 
945   // Create a process that will not be cleaned up
946   Process process(SpawnChild("SimpleChildProcess"));
947   process.InitializePriority();
948   const std::string unique_token = process.unique_token();
949   ASSERT_FALSE(unique_token.empty());
950 
951   EXPECT_TRUE(process.SetPriority(Process::Priority::kBestEffort));
952   EXPECT_EQ(process.GetPriority(), Process::Priority::kBestEffort);
953 
954   // Create a stale cgroup
955   std::string root = kFullRendererCgroupRoot;
956   std::string cgroup = root + "/" + unique_token;
957   std::vector<std::string> tokens = base::SplitString(
958       cgroup, "-", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
959   tokens[1] = "fake";
960   std::string fake_cgroup = base::JoinString(tokens, "-");
961   EXPECT_TRUE(base::CreateDirectory(FilePath(fake_cgroup)));
962 
963   // Clean up stale groups
964   Process::CleanUpStaleProcessStates();
965 
966   // validate the fake group is deleted
967   EXPECT_FALSE(base::DirectoryExists(FilePath(fake_cgroup)));
968 
969   // validate the active process cgroup is not deleted
970   EXPECT_TRUE(base::DirectoryExists(FilePath(cgroup)));
971 
972   // validate foreground and background are not deleted
973   EXPECT_TRUE(base::DirectoryExists(FilePath(root + "/foreground")));
974   EXPECT_TRUE(base::DirectoryExists(FilePath(root + "/background")));
975 
976   // clean up the process
977   EXPECT_TRUE(process.Terminate(0, false));
978   // Terminate should post a task, wait for it to run
979   task_env.RunUntilIdle();
980   EXPECT_FALSE(base::DirectoryExists(FilePath(cgroup)));
981 }
982 
TEST_F(ProcessTest,OneCgroupDoesNotCleanUpGroupsWithWrongPrefix)983 TEST_F(ProcessTest, OneCgroupDoesNotCleanUpGroupsWithWrongPrefix) {
984   if (!Process::OneGroupPerRendererEnabledForTesting())
985     return;
986 
987   base::test::TaskEnvironment task_env;
988 
989   // Create a process that will not be cleaned up
990   Process process(SpawnChild("SimpleChildProcess"));
991   process.InitializePriority();
992   const std::string unique_token = process.unique_token();
993   ASSERT_FALSE(unique_token.empty());
994 
995   EXPECT_TRUE(process.SetPriority(Process::Priority::kUserBlocking));
996   EXPECT_EQ(process.GetPriority(), Process::Priority::kUserBlocking);
997   std::string cgroup = GetProcessCpuCgroup(process);
998   EXPECT_FALSE(cgroup.empty());
999   EXPECT_NE(cgroup.find(unique_token), std::string::npos);
1000 
1001   // Create a stale cgroup
1002   FilePath cgroup_path = FilePath(std::string(kCgroupRoot) + cgroup);
1003   FilePath fake_cgroup = FilePath(kFullRendererCgroupRoot).AppendASCII("fake");
1004   EXPECT_TRUE(base::CreateDirectory(fake_cgroup));
1005 
1006   // Clean up stale groups
1007   Process::CleanUpStaleProcessStates();
1008 
1009   // validate the fake group is deleted
1010   EXPECT_TRUE(base::DirectoryExists(fake_cgroup));
1011   EXPECT_TRUE(base::DirectoryExists(cgroup_path));
1012 
1013   // clean up the process
1014   EXPECT_TRUE(process.SetPriority(Process::Priority::kBestEffort));
1015   EXPECT_EQ(process.GetPriority(), Process::Priority::kBestEffort);
1016   EXPECT_TRUE(process.Terminate(0, false));
1017   task_env.RunUntilIdle();
1018   EXPECT_FALSE(base::DirectoryExists(cgroup_path));
1019   base::DeleteFile(fake_cgroup);
1020 }
1021 #endif  // BUILDFLAG(IS_CHROMEOS)
1022 
1023 }  // namespace base
1024