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> |
8 #include <sys/resource.h> | 11 #include <sys/resource.h> |
| 12 #include <sys/syscall.h> |
9 | 13 |
| 14 #include "base/compiler_specific.h" |
10 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
11 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 17 #include "base/logging.h" |
13 #include "base/strings/string_split.h" | 18 #include "base/strings/string_split.h" |
14 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
15 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
| 21 #include "base/third_party/valgrind/valgrind.h" |
| 22 #include "build/build_config.h" |
16 | 23 |
17 namespace base { | 24 namespace base { |
18 | 25 |
19 namespace { | 26 namespace { |
20 | 27 |
21 const int kForegroundPriority = 0; | 28 const int kForegroundPriority = 0; |
22 | 29 |
23 #if defined(OS_CHROMEOS) | 30 #if defined(OS_CHROMEOS) |
24 // We are more aggressive in our lowering of background process priority | 31 // We are more aggressive in our lowering of background process priority |
25 // for chromeos as we have much more control over other processes running | 32 // 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... |
71 struct rlimit rlim; | 78 struct rlimit rlim; |
72 if ((getrlimit(RLIMIT_NICE, &rlim) == 0) && | 79 if ((getrlimit(RLIMIT_NICE, &rlim) == 0) && |
73 (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) { | 80 (20 - kForegroundPriority) <= static_cast<int>(rlim.rlim_cur)) { |
74 can_reraise_priority = true; | 81 can_reraise_priority = true; |
75 } | 82 } |
76 }; | 83 }; |
77 | 84 |
78 bool can_reraise_priority; | 85 bool can_reraise_priority; |
79 }; | 86 }; |
80 | 87 |
| 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 |
81 } // namespace | 134 } // namespace |
82 | 135 |
83 // static | 136 // static |
84 bool Process::CanBackgroundProcesses() { | 137 bool Process::CanBackgroundProcesses() { |
85 #if defined(OS_CHROMEOS) | 138 #if defined(OS_CHROMEOS) |
86 if (cgroups.Get().enabled) | 139 if (cgroups.Get().enabled) |
87 return true; | 140 return true; |
88 #endif | 141 #endif |
89 | 142 |
90 static LazyInstance<CheckForNicePermission> check_for_nice_permission = | 143 static LazyInstance<CheckForNicePermission> check_for_nice_permission = |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 | 182 |
130 if (!CanBackgroundProcesses()) | 183 if (!CanBackgroundProcesses()) |
131 return false; | 184 return false; |
132 | 185 |
133 int priority = background ? kBackgroundPriority : kForegroundPriority; | 186 int priority = background ? kBackgroundPriority : kForegroundPriority; |
134 int result = setpriority(PRIO_PROCESS, process_, priority); | 187 int result = setpriority(PRIO_PROCESS, process_, priority); |
135 DPCHECK(result == 0); | 188 DPCHECK(result == 0); |
136 return result == 0; | 189 return result == 0; |
137 } | 190 } |
138 | 191 |
| 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 |
139 } // namespace base | 231 } // namespace base |
OLD | NEW |