[M120 Migration][VD] Remove accessing oom_score_adj in zygote process
[platform/framework/web/chromium-efl.git] / content / browser / child_process_launcher_helper_linux.cc
1 // Copyright 2017 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/command_line.h"
6 #include "base/path_service.h"
7 #include "base/posix/global_descriptors.h"
8 #include "base/trace_event/trace_event.h"
9 #include "build/build_config.h"
10 #include "content/browser/child_process_launcher.h"
11 #include "content/browser/child_process_launcher_helper.h"
12 #include "content/browser/child_process_launcher_helper_posix.h"
13 #include "content/browser/sandbox_host_linux.h"
14 #include "content/browser/zygote_host/zygote_host_impl_linux.h"
15 #include "content/common/zygote/zygote_communication_linux.h"
16 #include "content/public/browser/child_process_launcher_utils.h"
17 #include "content/public/browser/content_browser_client.h"
18 #include "content/public/common/content_client.h"
19 #include "content/public/common/content_constants.h"
20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/result_codes.h"
22 #include "content/public/common/sandboxed_process_launcher_delegate.h"
23 #include "content/public/common/zygote/sandbox_support_linux.h"
24 #include "content/public/common/zygote/zygote_handle.h"
25 #include "sandbox/policy/linux/sandbox_linux.h"
26
27 namespace content {
28 namespace internal {
29
30 absl::optional<mojo::NamedPlatformChannel>
31 ChildProcessLauncherHelper::CreateNamedPlatformChannelOnLauncherThread() {
32   DCHECK(CurrentlyOnProcessLauncherTaskRunner());
33   return absl::nullopt;
34 }
35
36 void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
37   DCHECK(client_task_runner_->RunsTasksInCurrentSequence());
38 }
39
40 std::unique_ptr<FileMappedForLaunch>
41 ChildProcessLauncherHelper::GetFilesToMap() {
42   DCHECK(CurrentlyOnProcessLauncherTaskRunner());
43   return CreateDefaultPosixFilesToMap(
44       child_process_id(), mojo_channel_->remote_endpoint(),
45       file_data_->files_to_preload, GetProcessType(), command_line());
46 }
47
48 bool ChildProcessLauncherHelper::IsUsingLaunchOptions() {
49   return !GetZygoteForLaunch();
50 }
51
52 bool ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
53     PosixFileDescriptorInfo& files_to_register,
54     base::LaunchOptions* options) {
55   if (options) {
56     DCHECK(!GetZygoteForLaunch());
57     // Convert FD mapping to FileHandleMappingVector
58     options->fds_to_remap = files_to_register.GetMappingWithIDAdjustment(
59         base::GlobalDescriptors::kBaseDescriptor);
60
61     if (GetProcessType() == switches::kRendererProcess) {
62       const int sandbox_fd = SandboxHostLinux::GetInstance()->GetChildSocket();
63       options->fds_to_remap.emplace_back(sandbox_fd, GetSandboxFD());
64     }
65
66     options->environment = delegate_->GetEnvironment();
67   } else {
68     DCHECK(GetZygoteForLaunch());
69     // Environment variables could be supported in the future, but are not
70     // currently supported when launching with the zygote.
71     DCHECK(delegate_->GetEnvironment().empty());
72   }
73
74   return true;
75 }
76
77 ChildProcessLauncherHelper::Process
78 ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
79     const base::LaunchOptions* options,
80     std::unique_ptr<FileMappedForLaunch> files_to_register,
81     bool* is_synchronous_launch,
82     int* launch_result) {
83   *is_synchronous_launch = true;
84   Process process;
85   ZygoteCommunication* zygote_handle = GetZygoteForLaunch();
86 #if BUILDFLAG(IS_TIZEN) && !BUILDFLAG(IS_TIZEN_TV)
87   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
88           switches::kSingleProcess))
89     zygote_handle = nullptr;
90 #endif
91   if (zygote_handle) {
92     // TODO(crbug.com/569191): If chrome supported multiple zygotes they could
93     // be created lazily here, or in the delegate GetZygote() implementations.
94     // Additionally, the delegate could provide a UseGenericZygote() method.
95     base::ProcessHandle handle = zygote_handle->ForkRequest(
96         command_line()->argv(), files_to_register->GetMapping(),
97         GetProcessType());
98     *launch_result = LAUNCH_RESULT_SUCCESS;
99
100 #if !BUILDFLAG(IS_OPENBSD) && !BUILDFLAG(IS_TIZEN_TV)
101     if (handle) {
102       // It could be a renderer process or an utility process.
103       int oom_score = content::kMiscOomScore;
104       if (command_line()->GetSwitchValueASCII(switches::kProcessType) ==
105           switches::kRendererProcess)
106         oom_score = content::kLowestRendererOomScore;
107       ZygoteHostImpl::GetInstance()->AdjustRendererOOMScore(handle, oom_score);
108     }
109 #endif
110
111     process.process = base::Process(handle);
112     process.zygote = zygote_handle;
113   } else {
114     process.process = base::LaunchProcess(*command_line(), *options);
115     *launch_result = process.process.IsValid() ? LAUNCH_RESULT_SUCCESS
116                                                : LAUNCH_RESULT_FAILURE;
117   }
118
119 #if BUILDFLAG(IS_CHROMEOS)
120   if (GetProcessType() == switches::kRendererProcess) {
121     process.process.InitializePriority();
122   }
123 #endif
124
125   return process;
126 }
127
128 void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
129     const ChildProcessLauncherHelper::Process& process,
130     const base::LaunchOptions* options) {
131   // Reset any FDs still held open.
132   file_data_.reset();
133 }
134
135 ChildProcessTerminationInfo ChildProcessLauncherHelper::GetTerminationInfo(
136     const ChildProcessLauncherHelper::Process& process,
137     bool known_dead) {
138   ChildProcessTerminationInfo info;
139   if (process.zygote) {
140     info.status = process.zygote->GetTerminationStatus(
141         process.process.Handle(), known_dead, &info.exit_code);
142   } else if (known_dead) {
143     info.status = base::GetKnownDeadTerminationStatus(process.process.Handle(),
144                                                       &info.exit_code);
145   } else {
146     info.status =
147         base::GetTerminationStatus(process.process.Handle(), &info.exit_code);
148   }
149   return info;
150 }
151
152 // static
153 bool ChildProcessLauncherHelper::TerminateProcess(const base::Process& process,
154                                                   int exit_code) {
155   // TODO(https://crbug.com/818244): Determine whether we should also call
156   // EnsureProcessTerminated() to make sure of process-exit, and reap it.
157   return process.Terminate(exit_code, false);
158 }
159
160 // static
161 void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
162     ChildProcessLauncherHelper::Process process) {
163   TRACE_EVENT0("chromeos",
164                "ChildProcessLauncherHelper::ForceNormalProcessTerminationSync");
165   DCHECK(CurrentlyOnProcessLauncherTaskRunner());
166   process.process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
167   // On POSIX, we must additionally reap the child.
168   if (process.zygote) {
169     // If the renderer was created via a zygote, we have to proxy the reaping
170     // through the zygote process.
171     process.zygote->EnsureProcessTerminated(process.process.Handle());
172   } else {
173     base::EnsureProcessTerminated(std::move(process.process));
174   }
175 }
176
177 void ChildProcessLauncherHelper::SetProcessPriorityOnLauncherThread(
178     base::Process process,
179     base::Process::Priority priority) {
180   DCHECK(CurrentlyOnProcessLauncherTaskRunner());
181   if (process.CanSetPriority() && priority_ != priority) {
182     priority_ = priority;
183     process.SetPriority(priority);
184   }
185 }
186
187 ZygoteCommunication* ChildProcessLauncherHelper::GetZygoteForLaunch() {
188   return base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoZygote)
189              ? nullptr
190              : delegate_->GetZygote();
191 }
192
193 base::File OpenFileToShare(const base::FilePath& path,
194                            base::MemoryMappedFile::Region* region) {
195   base::FilePath exe_dir;
196   bool result = base::PathService::Get(base::BasePathKey::DIR_EXE, &exe_dir);
197   DCHECK(result);
198   base::File file(exe_dir.Append(path),
199                   base::File::FLAG_OPEN | base::File::FLAG_READ);
200   *region = base::MemoryMappedFile::Region::kWholeFile;
201   return file;
202 }
203
204 }  // namespace internal
205 }  // namespace content