| 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 |