diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-16 19:28:17 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-16 19:28:17 +0000 |
commit | 662183140166357f5088c40b34d1096d7a56fba7 (patch) | |
tree | fcb9f1e004ff1534fcc4b6eb8a95e26e0fdb7fb6 /base | |
parent | 3d79804c583eef9a0bc8bff30d41ca5a19ef1bc4 (diff) | |
download | chromium_src-662183140166357f5088c40b34d1096d7a56fba7.zip chromium_src-662183140166357f5088c40b34d1096d7a56fba7.tar.gz chromium_src-662183140166357f5088c40b34d1096d7a56fba7.tar.bz2 |
Linux: Guess the thread id for crashing renderers in a different PID namespace.
BUG=48997
TEST=Google Chrome gets valid crash reports for about:crash most of the time.
Review URL: http://codereview.chromium.org/2961008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52723 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/linux_util.cc | 47 | ||||
-rw-r--r-- | base/linux_util.h | 6 |
2 files changed, 53 insertions, 0 deletions
diff --git a/base/linux_util.cc b/base/linux_util.cc index d9fd065..dda6333 100644 --- a/base/linux_util.cc +++ b/base/linux_util.cc @@ -6,19 +6,24 @@ #include <dirent.h> #include <errno.h> +#include <fcntl.h> #include <glib.h> #include <stdlib.h> #include <sys/stat.h> +#include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> #include <vector> #include "base/command_line.h" #include "base/env_var.h" +#include "base/file_util.h" #include "base/lock.h" #include "base/path_service.h" #include "base/process_util.h" #include "base/singleton.h" +#include "base/scoped_ptr.h" #include "base/string_util.h" namespace { @@ -241,4 +246,46 @@ bool FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode) { return already_found; } +pid_t FindThreadIDWithSyscall(pid_t pid, const std::string& expected_data) { + char buf[256]; + snprintf(buf, sizeof(buf), "/proc/%d/task", pid); + DIR* task = opendir(buf); + if (!task) { + LOG(WARNING) << "Cannot open " << buf; + return -1; + } + + std::vector<pid_t> tids; + struct dirent* dent; + while ((dent = readdir(task))) { + char *endptr; + const unsigned long int tid_ul = strtoul(dent->d_name, &endptr, 10); + if (tid_ul == ULONG_MAX || *endptr) + continue; + tids.push_back(tid_ul); + } + closedir(task); + + scoped_array<char> syscall_data(new char[expected_data.length()]); + for (std::vector<pid_t>::const_iterator + i = tids.begin(); i != tids.end(); ++i) { + const pid_t current_tid = *i; + snprintf(buf, sizeof(buf), "/proc/%d/task/%d/syscall", pid, current_tid); + int fd = open(buf, O_RDONLY); + if (fd < 0) + continue; + bool read_ret = + file_util::ReadFromFD(fd, syscall_data.get(), expected_data.length()); + close(fd); + if (!read_ret) + continue; + + if (0 == strncmp(expected_data.c_str(), syscall_data.get(), + expected_data.length())) { + return current_tid; + } + } + return -1; +} + } // namespace base diff --git a/base/linux_util.h b/base/linux_util.h index e810674..a4ba9b6 100644 --- a/base/linux_util.h +++ b/base/linux_util.h @@ -29,6 +29,12 @@ bool FileDescriptorGetInode(ino_t* inode_out, int fd); // multiple processes hold the socket, this function returns false. bool FindProcessHoldingSocket(pid_t* pid_out, ino_t socket_inode); +// For a given process |pid|, look through all its threads and find the first +// thread with /proc/[pid]/task/[thread_id]/syscall whose first N bytes matches +// |expected_data|, where N is the length of |expected_data|. +// Returns the thread id or -1 on error. +pid_t FindThreadIDWithSyscall(pid_t pid, const std::string& expected_data); + } // namespace base #endif // BASE_LINUX_UTIL_H_ |