summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authorthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-16 19:28:17 +0000
committerthestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-16 19:28:17 +0000
commit662183140166357f5088c40b34d1096d7a56fba7 (patch)
treefcb9f1e004ff1534fcc4b6eb8a95e26e0fdb7fb6 /base
parent3d79804c583eef9a0bc8bff30d41ca5a19ef1bc4 (diff)
downloadchromium_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.cc47
-rw-r--r--base/linux_util.h6
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_