OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/process/process.h" | 5 #include "base/process/process.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <pthread.h> | |
9 #include <sched.h> | |
10 #include <setjmp.h> | |
11 #include <sys/resource.h> | 8 #include <sys/resource.h> |
12 #include <sys/syscall.h> | |
13 | 9 |
14 #include "base/compiler_specific.h" | |
15 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
16 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
17 #include "base/logging.h" | 12 #include "base/logging.h" |
18 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
19 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
20 #include "base/synchronization/lock.h" | 15 #include "base/synchronization/lock.h" |
21 #include "base/third_party/valgrind/valgrind.h" | |
22 #include "build/build_config.h" | |
23 | 16 |
24 namespace base { | 17 namespace base { |
25 | 18 |
26 namespace { | 19 namespace { |
27 | 20 |
28 const int kForegroundPriority = 0; | 21 const int kForegroundPriority = 0; |
29 | 22 |
30 #if defined(OS_CHROMEOS) | 23 #if defined(OS_CHROMEOS) |
31 // We are more aggressive in our lowering of background process priority | 24 // We are more aggressive in our lowering of background process priority |
32 // for chromeos as we have much more control over other processes running | 25 // for chromeos as we have much more control over other processes running |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 struct rlimit rlim; | 71 struct rlimit rlim; |
79 if ((getrlimit(RLIMIT_NICE, &rlim) == 0) && | 72 if ((getrlimit(RLIMIT_NICE, &rlim) == 0) && |
80 (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) { | 73 (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) { |
81 can_reraise_priority = true; | 74 can_reraise_priority = true; |
82 } | 75 } |
83 }; | 76 }; |
84 | 77 |
85 bool can_reraise_priority; | 78 bool can_reraise_priority; |
86 }; | 79 }; |
87 | 80 |
88 bool IsRunningOnValgrind() { | |
89 return RUNNING_ON_VALGRIND; | |
90 } | |
91 | |
92 // This function runs on the stack specified on the clone call. It uses longjmp | |
93 // to switch back to the original stack so the child can return from sys_clone. | |
94 int CloneHelper(void* arg) { | |
95 jmp_buf* env_ptr = reinterpret_cast<jmp_buf*>(arg); | |
96 longjmp(*env_ptr, 1); | |
97 | |
98 // Should not be reached. | |
99 RAW_CHECK(false); | |
100 return 1; | |
101 } | |
102 | |
103 // This function is noinline to ensure that stack_buf is below the stack pointer | |
104 // that is saved when setjmp is called below. This is needed because when | |
105 // compiled with FORTIFY_SOURCE, glibc's longjmp checks that the stack is moved | |
106 // upwards. See crbug.com/442912 for more details. | |
107 #if defined(ADDRESS_SANITIZER) | |
108 // Disable AddressSanitizer instrumentation for this function to make sure | |
109 // |stack_buf| is allocated on thread stack instead of ASan's fake stack. | |
110 // Under ASan longjmp() will attempt to clean up the area between the old and | |
111 // new stack pointers and print a warning that may confuse the user. | |
112 __attribute__((no_sanitize_address)) | |
113 #endif | |
114 NOINLINE pid_t CloneAndLongjmpInChild(unsigned long flags, | |
115 pid_t* ptid, | |
116 pid_t* ctid, | |
117 jmp_buf* env) { | |
118 // We use the libc clone wrapper instead of making the syscall | |
119 // directly because making the syscall may fail to update the libc's | |
120 // internal pid cache. The libc interface unfortunately requires | |
121 // specifying a new stack, so we use setjmp/longjmp to emulate | |
122 // fork-like behavior. | |
123 char stack_buf[PTHREAD_STACK_MIN]; | |
124 #if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY) || \ | |
125 defined(ARCH_CPU_MIPS64_FAMILY) || defined(ARCH_CPU_MIPS_FAMILY) | |
126 // The stack grows downward. | |
127 void* stack = stack_buf + sizeof(stack_buf); | |
128 #else | |
129 #error "Unsupported architecture" | |
130 #endif | |
131 return clone(&CloneHelper, stack, flags, env, ptid, nullptr, ctid); | |
132 } | |
133 | |
134 } // namespace | 81 } // namespace |
135 | 82 |
136 // static | 83 // static |
137 bool Process::CanBackgroundProcesses() { | 84 bool Process::CanBackgroundProcesses() { |
138 #if defined(OS_CHROMEOS) | 85 #if defined(OS_CHROMEOS) |
139 if (cgroups.Get().enabled) | 86 if (cgroups.Get().enabled) |
140 return true; | 87 return true; |
141 #endif | 88 #endif |
142 | 89 |
143 static LazyInstance<CheckForNicePermission> check_for_nice_permission = | 90 static LazyInstance<CheckForNicePermission> check_for_nice_permission = |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 | 129 |
183 if (!CanBackgroundProcesses()) | 130 if (!CanBackgroundProcesses()) |
184 return false; | 131 return false; |
185 | 132 |
186 int priority = background ? kBackgroundPriority : kForegroundPriority; | 133 int priority = background ? kBackgroundPriority : kForegroundPriority; |
187 int result = setpriority(PRIO_PROCESS, process_, priority); | 134 int result = setpriority(PRIO_PROCESS, process_, priority); |
188 DPCHECK(result == 0); | 135 DPCHECK(result == 0); |
189 return result == 0; | 136 return result == 0; |
190 } | 137 } |
191 | 138 |
192 pid_t ForkWithFlags(unsigned long flags, pid_t* ptid, pid_t* ctid) { | |
193 const bool clone_tls_used = flags & CLONE_SETTLS; | |
194 const bool invalid_ctid = | |
195 (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) && !ctid; | |
196 const bool invalid_ptid = (flags & CLONE_PARENT_SETTID) && !ptid; | |
197 | |
198 // We do not support CLONE_VM. | |
199 const bool clone_vm_used = flags & CLONE_VM; | |
200 | |
201 if (clone_tls_used || invalid_ctid || invalid_ptid || clone_vm_used) { | |
202 RAW_LOG(FATAL, "Invalid usage of ForkWithFlags"); | |
203 } | |
204 | |
205 // Valgrind's clone implementation does not support specifiying a child_stack | |
206 // without CLONE_VM, so we cannot use libc's clone wrapper when running under | |
207 // Valgrind. As a result, the libc pid cache may be incorrect under Valgrind. | |
208 // See crbug.com/442817 for more details. | |
209 if (IsRunningOnValgrind()) { | |
210 // See kernel/fork.c in Linux. There is different ordering of sys_clone | |
211 // parameters depending on CONFIG_CLONE_BACKWARDS* configuration options. | |
212 #if defined(ARCH_CPU_X86_64) | |
213 return syscall(__NR_clone, flags, nullptr, ptid, ctid, nullptr); | |
214 #elif defined(ARCH_CPU_X86) || defined(ARCH_CPU_ARM_FAMILY) || \ | |
215 defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY) | |
216 // CONFIG_CLONE_BACKWARDS defined. | |
217 return syscall(__NR_clone, flags, nullptr, ptid, nullptr, ctid); | |
218 #else | |
219 #error "Unsupported architecture" | |
220 #endif | |
221 } | |
222 | |
223 jmp_buf env; | |
224 if (setjmp(env) == 0) { | |
225 return CloneAndLongjmpInChild(flags, ptid, ctid, &env); | |
226 } | |
227 | |
228 return 0; | |
229 } | |
230 | |
231 } // namespace base | 139 } // namespace base |
OLD | NEW |