diff options
Diffstat (limited to 'daemon/Proc.cpp')
-rw-r--r-- | daemon/Proc.cpp | 106 |
1 files changed, 71 insertions, 35 deletions
diff --git a/daemon/Proc.cpp b/daemon/Proc.cpp index e0b9e22..9f01770 100644 --- a/daemon/Proc.cpp +++ b/daemon/Proc.cpp | |||
@@ -57,14 +57,57 @@ static bool readProcStat(ProcStat *const ps, const char *const pathname, DynBuf | |||
57 | return true; | 57 | return true; |
58 | } | 58 | } |
59 | 59 | ||
60 | static bool readProcTask(Buffer *const buffer, const int pid, const char *const image, DynBuf *const printb, DynBuf *const b) { | 60 | static const char *readProcExe(DynBuf *const printb, const int pid, const int tid, DynBuf *const b) { |
61 | if (tid == -1 ? !printb->printf("/proc/%i/exe", pid) | ||
62 | : !printb->printf("/proc/%i/task/%i/exe", pid, tid)) { | ||
63 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | ||
64 | return NULL; | ||
65 | } | ||
66 | |||
67 | const int err = b->readlink(printb->getBuf()); | ||
68 | const char *image; | ||
69 | if (err == 0) { | ||
70 | image = strrchr(b->getBuf(), '/'); | ||
71 | if (image == NULL) { | ||
72 | image = b->getBuf(); | ||
73 | } else { | ||
74 | ++image; | ||
75 | } | ||
76 | } else if (err == -ENOENT) { | ||
77 | // readlink /proc/[pid]/exe returns ENOENT for kernel threads | ||
78 | image = "\0"; | ||
79 | } else { | ||
80 | logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__); | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | // Android apps are run by app_process but the cmdline is changed to reference the actual app name | ||
85 | if (strcmp(image, "app_process") != 0) { | ||
86 | return image; | ||
87 | } | ||
88 | |||
89 | if (tid == -1 ? !printb->printf("/proc/%i/cmdline", pid) | ||
90 | : !printb->printf("/proc/%i/task/%i/cmdline", pid, tid)) { | ||
91 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
95 | if (!b->read(printb->getBuf())) { | ||
96 | logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the thread exited", __FUNCTION__, __FILE__, __LINE__); | ||
97 | return NULL; | ||
98 | } | ||
99 | |||
100 | return b->getBuf(); | ||
101 | } | ||
102 | |||
103 | static bool readProcTask(Buffer *const buffer, const int pid, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2) { | ||
61 | bool result = false; | 104 | bool result = false; |
62 | 105 | ||
63 | if (!b->printf("/proc/%i/task", pid)) { | 106 | if (!b1->printf("/proc/%i/task", pid)) { |
64 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | 107 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); |
65 | return result; | 108 | return result; |
66 | } | 109 | } |
67 | DIR *task = opendir(b->getBuf()); | 110 | DIR *task = opendir(b1->getBuf()); |
68 | if (task == NULL) { | 111 | if (task == NULL) { |
69 | logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); | 112 | logg->logMessage("%s(%s:%i): opendir failed", __FUNCTION__, __FILE__, __LINE__); |
70 | return result; | 113 | return result; |
@@ -84,11 +127,17 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const | |||
84 | goto fail; | 127 | goto fail; |
85 | } | 128 | } |
86 | ProcStat ps; | 129 | ProcStat ps; |
87 | if (!readProcStat(&ps, printb->getBuf(), b)) { | 130 | if (!readProcStat(&ps, printb->getBuf(), b1)) { |
88 | logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); | 131 | logg->logMessage("%s(%s:%i): readProcStat failed", __FUNCTION__, __FILE__, __LINE__); |
89 | goto fail; | 132 | goto fail; |
90 | } | 133 | } |
91 | 134 | ||
135 | const char *const image = readProcExe(printb, pid, tid, b2); | ||
136 | if (image == NULL) { | ||
137 | logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); | ||
138 | goto fail; | ||
139 | } | ||
140 | |||
92 | buffer->comm(pid, tid, image, ps.comm); | 141 | buffer->comm(pid, tid, image, ps.comm); |
93 | } | 142 | } |
94 | 143 | ||
@@ -100,7 +149,7 @@ static bool readProcTask(Buffer *const buffer, const int pid, const char *const | |||
100 | return result; | 149 | return result; |
101 | } | 150 | } |
102 | 151 | ||
103 | bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) { | 152 | bool readProc(Buffer *const buffer, bool sendMaps, DynBuf *const printb, DynBuf *const b1, DynBuf *const b2, DynBuf *const b3) { |
104 | bool result = false; | 153 | bool result = false; |
105 | 154 | ||
106 | DIR *proc = opendir("/proc"); | 155 | DIR *proc = opendir("/proc"); |
@@ -128,42 +177,29 @@ bool readProc(Buffer *const buffer, DynBuf *const printb, DynBuf *const b1, DynB | |||
128 | goto fail; | 177 | goto fail; |
129 | } | 178 | } |
130 | 179 | ||
131 | if (!printb->printf("/proc/%i/exe", pid)) { | 180 | if (sendMaps) { |
132 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | 181 | if (!printb->printf("/proc/%i/maps", pid)) { |
133 | goto fail; | 182 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); |
134 | } | 183 | goto fail; |
135 | const int err = b1->readlink(printb->getBuf()); | 184 | } |
136 | const char *image; | 185 | if (!b2->read(printb->getBuf())) { |
137 | if (err == 0) { | 186 | logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__); |
138 | image = strrchr(b1->getBuf(), '/'); | 187 | // This is not a fatal error - the process just doesn't exist any more |
139 | if (image == NULL) { | 188 | continue; |
140 | image = b1->getBuf(); | ||
141 | } else { | ||
142 | ++image; | ||
143 | } | 189 | } |
144 | } else if (err == -ENOENT) { | ||
145 | // readlink /proc/[pid]/exe returns ENOENT for kernel threads | ||
146 | image = "\0"; | ||
147 | } else { | ||
148 | logg->logMessage("%s(%s:%i): DynBuf::readlink failed", __FUNCTION__, __FILE__, __LINE__); | ||
149 | goto fail; | ||
150 | } | ||
151 | 190 | ||
152 | if (!printb->printf("/proc/%i/maps", pid)) { | 191 | buffer->maps(pid, pid, b2->getBuf()); |
153 | logg->logMessage("%s(%s:%i): DynBuf::printf failed", __FUNCTION__, __FILE__, __LINE__); | ||
154 | goto fail; | ||
155 | } | 192 | } |
156 | if (!b2->read(printb->getBuf())) { | ||
157 | logg->logMessage("%s(%s:%i): DynBuf::read failed, likely because the process exited", __FUNCTION__, __FILE__, __LINE__); | ||
158 | // This is not a fatal error - the process just doesn't exist any more | ||
159 | continue; | ||
160 | } | ||
161 | |||
162 | buffer->maps(pid, pid, b2->getBuf()); | ||
163 | if (ps.numThreads <= 1) { | 193 | if (ps.numThreads <= 1) { |
194 | const char *const image = readProcExe(printb, pid, -1, b1); | ||
195 | if (image == NULL) { | ||
196 | logg->logMessage("%s(%s:%i): readImage failed", __FUNCTION__, __FILE__, __LINE__); | ||
197 | goto fail; | ||
198 | } | ||
199 | |||
164 | buffer->comm(pid, pid, image, ps.comm); | 200 | buffer->comm(pid, pid, image, ps.comm); |
165 | } else { | 201 | } else { |
166 | if (!readProcTask(buffer, pid, image, printb, b3)) { | 202 | if (!readProcTask(buffer, pid, printb, b1, b3)) { |
167 | logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__); | 203 | logg->logMessage("%s(%s:%i): readProcTask failed", __FUNCTION__, __FILE__, __LINE__); |
168 | goto fail; | 204 | goto fail; |
169 | } | 205 | } |