diff options
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_ |