Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/linux_util.h" | 5 #include "base/linux_util.h" |
| 6 | 6 |
| 7 #include <dirent.h> | 7 #include <dirent.h> |
| 8 #include <errno.h> | 8 #include <errno.h> |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <stdlib.h> | 10 #include <stdlib.h> |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 DCHECK_EQ(STATE_CHECK_STARTED, state_); | 64 DCHECK_EQ(STATE_CHECK_STARTED, state_); |
| 65 state_ = STATE_CHECK_FINISHED; | 65 state_ = STATE_CHECK_FINISHED; |
| 66 } | 66 } |
| 67 | 67 |
| 68 private: | 68 private: |
| 69 base::Lock lock_; | 69 base::Lock lock_; |
| 70 LinuxDistroState state_; | 70 LinuxDistroState state_; |
| 71 }; | 71 }; |
| 72 #endif // if defined(OS_LINUX) | 72 #endif // if defined(OS_LINUX) |
| 73 | 73 |
| 74 // expected prefix of the target of the /proc/self/fd/%d link for a socket | |
| 75 const char kSocketLinkPrefix[] = "socket:["; | |
| 76 | |
| 77 // Parse a symlink in /proc/pid/fd/$x and return the inode number of the | |
| 78 // socket. | |
| 79 // inode_out: (output) set to the inode number on success | |
| 80 // path: e.g. /proc/1234/fd/5 (must be a UNIX domain socket descriptor) | |
| 81 // log: if true, log messages about failure details | |
| 82 bool ProcPathGetInode(ino_t* inode_out, const char* path, bool log = false) { | |
| 83 DCHECK(inode_out); | |
| 84 DCHECK(path); | |
| 85 | |
| 86 char buf[256]; | |
| 87 const ssize_t n = readlink(path, buf, sizeof(buf) - 1); | |
| 88 if (n == -1) { | |
| 89 if (log) { | |
| 90 DLOG(WARNING) << "Failed to read the inode number for a socket from /proc" | |
| 91 "(" << errno << ")"; | |
| 92 } | |
| 93 return false; | |
| 94 } | |
| 95 buf[n] = 0; | |
| 96 | |
| 97 if (memcmp(kSocketLinkPrefix, buf, sizeof(kSocketLinkPrefix) - 1)) { | |
| 98 if (log) { | |
| 99 DLOG(WARNING) << "The descriptor passed from the crashing process wasn't " | |
| 100 " a UNIX domain socket."; | |
| 101 } | |
| 102 return false; | |
| 103 } | |
| 104 | |
| 105 char* endptr; | |
| 106 const unsigned long long int inode_ul = | |
| 107 strtoull(buf + sizeof(kSocketLinkPrefix) - 1, &endptr, 10); | |
| 108 if (*endptr != ']') | |
| 109 return false; | |
| 110 | |
| 111 if (inode_ul == ULLONG_MAX) { | |
| 112 if (log) { | |
| 113 DLOG(WARNING) << "Failed to parse a socket's inode number: the number " | |
| 114 "was too large. Please report this bug: " << buf; | |
| 115 } | |
| 116 return false; | |
| 117 } | |
| 118 | |
| 119 *inode_out = inode_ul; | |
| 120 return true; | |
| 121 } | |
| 122 | |
| 123 } // namespace | 74 } // namespace |
| 124 | 75 |
| 125 namespace base { | 76 namespace base { |
| 126 | 77 |
| 127 const char kFindInodeSwitch[] = "--find-inode"; | 78 const char kFindInodeSwitch[] = "--find-inode"; |
|
Lei Zhang
2014/05/13 00:09:54
This is dead code as well.
mdempsky
2014/05/13 00:11:13
Yep, I already mailed out https://codereview.chrom
| |
| 128 | 79 |
| 129 // Account for the terminating null character. | 80 // Account for the terminating null character. |
| 130 static const int kDistroSize = 128 + 1; | 81 static const int kDistroSize = 128 + 1; |
| 131 | 82 |
| 132 // We use this static string to hold the Linux distro info. If we | 83 // We use this static string to hold the Linux distro info. If we |
| 133 // crash, the crash handler code will send this in the crash dump. | 84 // crash, the crash handler code will send this in the crash dump. |
| 134 char g_linux_distro[kDistroSize] = | 85 char g_linux_distro[kDistroSize] = |
| 135 #if defined(OS_CHROMEOS) | 86 #if defined(OS_CHROMEOS) |
| 136 "CrOS"; | 87 "CrOS"; |
| 137 #elif defined(OS_ANDROID) | 88 #elif defined(OS_ANDROID) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 return "Unknown"; | 124 return "Unknown"; |
| 174 #endif | 125 #endif |
| 175 } | 126 } |
| 176 | 127 |
| 177 void SetLinuxDistro(const std::string& distro) { | 128 void SetLinuxDistro(const std::string& distro) { |
| 178 std::string trimmed_distro; | 129 std::string trimmed_distro; |
| 179 base::TrimWhitespaceASCII(distro, base::TRIM_ALL, &trimmed_distro); | 130 base::TrimWhitespaceASCII(distro, base::TRIM_ALL, &trimmed_distro); |
| 180 base::strlcpy(g_linux_distro, trimmed_distro.c_str(), kDistroSize); | 131 base::strlcpy(g_linux_distro, trimmed_distro.c_str(), kDistroSize); |
| 181 } | 132 } |
| 182 | 133 |
| 183 bool FileDescriptorGetInode(ino_t* inode_out, int fd) { | |
| 184 DCHECK(inode_out); | |
| 185 | |
| 186 struct stat buf; | |
| 187 if (fstat(fd, &buf) < 0) | |
| 188 return false; | |
| 189 | |
| 190 if (!S_ISSOCK(buf.st_mode)) | |
| 191 return false; | |
| 192 | |
| 193 *inode_out = buf.st_ino; | |
| 194 return true; | |
| 195 } | |
| 196 | |
| 197 bool FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode) { | |
| 198 DCHECK(pid_out); | |
| 199 bool already_found = false; | |
| 200 | |
| 201 DIR* proc = opendir("/proc"); | |
| 202 if (!proc) { | |
| 203 DLOG(WARNING) << "Cannot open /proc"; | |
| 204 return false; | |
| 205 } | |
| 206 | |
| 207 std::vector<pid_t> pids; | |
| 208 | |
| 209 struct dirent* dent; | |
| 210 while ((dent = readdir(proc))) { | |
| 211 char* endptr; | |
| 212 const unsigned long int pid_ul = strtoul(dent->d_name, &endptr, 10); | |
| 213 if (pid_ul == ULONG_MAX || *endptr) | |
| 214 continue; | |
| 215 pids.push_back(pid_ul); | |
| 216 } | |
| 217 closedir(proc); | |
| 218 | |
| 219 for (std::vector<pid_t>::const_iterator | |
| 220 i = pids.begin(); i != pids.end(); ++i) { | |
| 221 const pid_t current_pid = *i; | |
| 222 char buf[256]; | |
| 223 snprintf(buf, sizeof(buf), "/proc/%d/fd", current_pid); | |
| 224 DIR* fd = opendir(buf); | |
| 225 if (!fd) | |
| 226 continue; | |
| 227 | |
| 228 while ((dent = readdir(fd))) { | |
| 229 if (snprintf(buf, sizeof(buf), "/proc/%d/fd/%s", current_pid, | |
| 230 dent->d_name) >= static_cast<int>(sizeof(buf))) { | |
| 231 continue; | |
| 232 } | |
| 233 | |
| 234 ino_t fd_inode = static_cast<ino_t>(-1); | |
| 235 if (ProcPathGetInode(&fd_inode, buf)) { | |
| 236 if (fd_inode == socket_inode) { | |
| 237 if (already_found) { | |
| 238 closedir(fd); | |
| 239 return false; | |
| 240 } | |
| 241 | |
| 242 already_found = true; | |
| 243 *pid_out = current_pid; | |
| 244 break; | |
| 245 } | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 closedir(fd); | |
| 250 } | |
| 251 | |
| 252 return already_found; | |
| 253 } | |
| 254 | |
| 255 pid_t FindThreadIDWithSyscall(pid_t pid, const std::string& expected_data, | 134 pid_t FindThreadIDWithSyscall(pid_t pid, const std::string& expected_data, |
| 256 bool* syscall_supported) { | 135 bool* syscall_supported) { |
| 257 char buf[256]; | 136 char buf[256]; |
| 258 snprintf(buf, sizeof(buf), "/proc/%d/task", pid); | 137 snprintf(buf, sizeof(buf), "/proc/%d/task", pid); |
| 259 | 138 |
| 260 if (syscall_supported != NULL) | 139 if (syscall_supported != NULL) |
| 261 *syscall_supported = false; | 140 *syscall_supported = false; |
| 262 | 141 |
| 263 DIR* task = opendir(buf); | 142 DIR* task = opendir(buf); |
| 264 if (!task) { | 143 if (!task) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 294 | 173 |
| 295 if (0 == strncmp(expected_data.c_str(), syscall_data.get(), | 174 if (0 == strncmp(expected_data.c_str(), syscall_data.get(), |
| 296 expected_data.length())) { | 175 expected_data.length())) { |
| 297 return current_tid; | 176 return current_tid; |
| 298 } | 177 } |
| 299 } | 178 } |
| 300 return -1; | 179 return -1; |
| 301 } | 180 } |
| 302 | 181 |
| 303 } // namespace base | 182 } // namespace base |
| OLD | NEW |