Stefan Schuermans commited on 2021-03-09 20:37:39
Showing 4 changed files, with 26 additions and 21 deletions.
A child process of fork() does not have a begin event and thus, nothing was known about its parent. Adding the ppid to the end event establishes the relationship to its parent process.
| ... | ... |
@@ -34,6 +34,10 @@ int uptev_proc_end(void **data, size_t *size) {
|
| 34 | 34 |
|
| 35 | 35 |
struct _Uproctrace__ProcEnd proc_end = UPROCTRACE__PROC_END__INIT; |
| 36 | 36 |
proc_end.pid = getpid(); |
| 37 |
+ // ppid also in end event because child of fork() has no begin event |
|
| 38 |
+ proc_end.has_ppid = 1; |
|
| 39 |
+ proc_end.ppid = getppid(); |
|
| 40 |
+ |
|
| 37 | 41 |
proc_end.cpu_time = &cpu_time; |
| 38 | 42 |
|
| 39 | 43 |
struct rusage usage; |
| ... | ... |
@@ -82,6 +82,7 @@ class ProcBeginOrEnd(BaseEvent): |
| 82 | 82 |
super().__init__(pb2_ev) |
| 83 | 83 |
self._process = None |
| 84 | 84 |
self._pid = None |
| 85 |
+ self._ppid = None |
|
| 85 | 86 |
|
| 86 | 87 |
@property |
| 87 | 88 |
def pid(self) -> int: |
| ... | ... |
@@ -90,6 +91,13 @@ class ProcBeginOrEnd(BaseEvent): |
| 90 | 91 |
""" |
| 91 | 92 |
return self._pid |
| 92 | 93 |
|
| 94 |
+ @property |
|
| 95 |
+ def ppid(self) -> int: |
|
| 96 |
+ """ |
|
| 97 |
+ ID of parent process. |
|
| 98 |
+ """ |
|
| 99 |
+ return self._ppid |
|
| 100 |
+ |
|
| 93 | 101 |
@property |
| 94 | 102 |
def process(self): |
| 95 | 103 |
""" |
| ... | ... |
@@ -123,13 +131,6 @@ class ProcBegin(ProcBeginOrEnd): |
| 123 | 131 |
self._environ = self._pb2GetStringList( |
| 124 | 132 |
p_b.environ) if p_b.HasField('environ') else None
|
| 125 | 133 |
|
| 126 |
- @property |
|
| 127 |
- def ppid(self) -> int: |
|
| 128 |
- """ |
|
| 129 |
- ID of parent process. |
|
| 130 |
- """ |
|
| 131 |
- return self._ppid |
|
| 132 |
- |
|
| 133 | 134 |
@property |
| 134 | 135 |
def exe(self) -> str: |
| 135 | 136 |
""" |
| ... | ... |
@@ -173,6 +174,7 @@ class ProcEnd(ProcBeginOrEnd): |
| 173 | 174 |
super().__init__(pb2_ev) |
| 174 | 175 |
p_e = pb2_ev.proc_end |
| 175 | 176 |
self._pid = p_e.pid |
| 177 |
+ self._ppid = p_e.ppid if p_e.HasField('ppid') else None
|
|
| 176 | 178 |
self._cpu_time = self._pb2GetTimespec( |
| 177 | 179 |
p_e.cpu_time) if p_e.HasField('cpu_time') else None
|
| 178 | 180 |
self._user_time = self._pb2GetTimespec( |
| ... | ... |
@@ -188,13 +190,6 @@ class ProcEnd(ProcBeginOrEnd): |
| 188 | 190 |
self._n_v_csw = p_e.n_v_csw if p_e.HasField('n_v_csw') else None
|
| 189 | 191 |
self._n_iv_csw = p_e.n_iv_csw if p_e.HasField('n_iv_csw') else None
|
| 190 | 192 |
|
| 191 |
- @property |
|
| 192 |
- def pid(self) -> int: |
|
| 193 |
- """ |
|
| 194 |
- ID of process. |
|
| 195 |
- """ |
|
| 196 |
- return self._pid |
|
| 197 |
- |
|
| 198 | 193 |
@property |
| 199 | 194 |
def cpu_time(self) -> float: |
| 200 | 195 |
""" |
| ... | ... |
@@ -171,20 +171,20 @@ class Process(): |
| 171 | 171 |
""" |
| 172 | 172 |
Linux process ID. |
| 173 | 173 |
""" |
| 174 |
- if self._begin is not None: |
|
| 175 |
- return self._begin.pid |
|
| 176 |
- if self._end is not None: |
|
| 177 |
- return self._end.pid |
|
| 178 |
- return None |
|
| 174 |
+ return self._pid |
|
| 179 | 175 |
|
| 180 | 176 |
@property |
| 181 | 177 |
def ppid(self): |
| 182 | 178 |
""" |
| 183 | 179 |
Linux process ID of parent process. |
| 184 | 180 |
""" |
| 185 |
- if self._begin is None: |
|
| 186 |
- return None |
|
| 181 |
+ if self._begin is not None: |
|
| 182 |
+ if self._begin.ppid is not None: |
|
| 187 | 183 |
return self._begin.ppid |
| 184 |
+ if self._end is not None: |
|
| 185 |
+ if self._end.ppid: |
|
| 186 |
+ return self._end.ppid |
|
| 187 |
+ return None |
|
| 188 | 188 |
|
| 189 | 189 |
@property |
| 190 | 190 |
def proc_id(self): |
| ... | ... |
@@ -355,6 +355,10 @@ class Processes(uproctrace.parse.Visitor): |
| 355 | 355 |
# set end event of process and process of end event |
| 356 | 356 |
proc.setEnd(proc_end) |
| 357 | 357 |
proc_end.setProcess(proc) |
| 358 |
+ # add process to parent if available |
|
| 359 |
+ if proc_end.ppid is not None: |
|
| 360 |
+ parent = self._getProcess(proc_end.ppid) |
|
| 361 |
+ self._parentChild(parent, proc) |
|
| 358 | 362 |
# remove process from dict of current processes (it ended) |
| 359 | 363 |
# - it is guaranteed to be in it, because it came from _getProcess() |
| 360 | 364 |
del self._current_processes[proc_end.pid] |
| ... | ... |
@@ -22,6 +22,8 @@ message proc_begin {
|
| 22 | 22 |
|
| 23 | 23 |
message proc_end {
|
| 24 | 24 |
required int32 pid = 1; |
| 25 |
+ optional int32 ppid = 12; ///< pid of parent process (important for fork(), |
|
| 26 |
+ ///< because child of fork has no proc_begin event) |
|
| 25 | 27 |
/// fields from clock_gettime |
| 26 | 28 |
//@{
|
| 27 | 29 |
optional timespec cpu_time = 2; ///< CPU time usage |
| 28 | 30 |