|  | #include "cache.h" | 
|  |  | 
|  | #include "strbuf.h" | 
|  | #include "strvec.h" | 
|  | #include "trace2.h" | 
|  |  | 
|  | /* | 
|  | * We need more complex parsing in stat_parent_pid() and | 
|  | * parse_proc_stat() below than a dumb fscanf(). That's because while | 
|  | * the statcomm field is surrounded by parentheses, the process itself | 
|  | * is free to insert any arbitrary byte sequence its its name. That | 
|  | * can include newlines, spaces, closing parentheses etc. | 
|  | * | 
|  | * See do_task_stat() in fs/proc/array.c in linux.git, this is in | 
|  | * contrast with the escaped version of the name found in | 
|  | * /proc/%d/status. | 
|  | * | 
|  | * So instead of using fscanf() we'll read N bytes from it, look for | 
|  | * the first "(", and then the last ")", anything in-between is our | 
|  | * process name. | 
|  | * | 
|  | * How much N do we need? On Linux /proc/sys/kernel/pid_max is 2^15 by | 
|  | * default, but it can be raised set to values of up to 2^22. So | 
|  | * that's 7 digits for a PID. We have 2 PIDs in the first four fields | 
|  | * we're interested in, so 2 * 7 = 14. | 
|  | * | 
|  | * We then have 3 spaces between those four values, and we'd like to | 
|  | * get to the space between the 4th and the 5th (the "pgrp" field) to | 
|  | * make sure we read the entire "ppid" field. So that brings us up to | 
|  | * 14 + 3 + 1 = 18. Add the two parentheses around the "comm" value | 
|  | * and it's 20. The "state" value itself is then one character (now at | 
|  | * 21). | 
|  | * | 
|  | * Finally the maximum length of the "comm" name itself is 15 | 
|  | * characters, e.g. a setting of "123456789abcdefg" will be truncated | 
|  | * to "123456789abcdef". See PR_SET_NAME in prctl(2). So all in all | 
|  | * we'd need to read 21 + 15 = 36 bytes. | 
|  | * | 
|  | * Let's just read 2^6 (64) instead for good measure. If PID_MAX ever | 
|  | * grows past 2^22 we'll be future-proof. We'll then anchor at the | 
|  | * last ")" we find to locate the parent PID. | 
|  | */ | 
|  | #define STAT_PARENT_PID_READ_N 64 | 
|  |  | 
|  | static int parse_proc_stat(struct strbuf *sb, struct strbuf *name, | 
|  | int *statppid) | 
|  | { | 
|  | const char *comm_lhs = strchr(sb->buf, '('); | 
|  | const char *comm_rhs = strrchr(sb->buf, ')'); | 
|  | const char *ppid_lhs, *ppid_rhs; | 
|  | char *p; | 
|  | pid_t ppid; | 
|  |  | 
|  | if (!comm_lhs || !comm_rhs) | 
|  | goto bad_kernel; | 
|  |  | 
|  | /* | 
|  | * We're at the ")", that's followed by " X ", where X is a | 
|  | * single "state" character. So advance by 4 bytes. | 
|  | */ | 
|  | ppid_lhs = comm_rhs + 4; | 
|  |  | 
|  | /* | 
|  | * Read until the space between the "ppid" and "pgrp" fields | 
|  | * to make sure we're anchored after the untruncated "ppid" | 
|  | * field.. | 
|  | */ | 
|  | ppid_rhs = strchr(ppid_lhs, ' '); | 
|  | if (!ppid_rhs) | 
|  | goto bad_kernel; | 
|  |  | 
|  | ppid = strtol(ppid_lhs, &p, 10); | 
|  | if (ppid_rhs == p) { | 
|  | const char *comm = comm_lhs + 1; | 
|  | size_t commlen = comm_rhs - comm; | 
|  |  | 
|  | strbuf_add(name, comm, commlen); | 
|  | *statppid = ppid; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | bad_kernel: | 
|  | /* | 
|  | * We were able to read our STAT_PARENT_PID_READ_N bytes from | 
|  | * /proc/%d/stat, but the content is bad. Broken kernel? | 
|  | * Should not happen, but handle it gracefully. | 
|  | */ | 
|  | return -1; | 
|  | } | 
|  |  | 
|  | static int stat_parent_pid(pid_t pid, struct strbuf *name, int *statppid) | 
|  | { | 
|  | struct strbuf procfs_path = STRBUF_INIT; | 
|  | struct strbuf sb = STRBUF_INIT; | 
|  | FILE *fp; | 
|  | int ret = -1; | 
|  |  | 
|  | /* try to use procfs if it's present. */ | 
|  | strbuf_addf(&procfs_path, "/proc/%d/stat", pid); | 
|  | fp = fopen(procfs_path.buf, "r"); | 
|  | if (!fp) | 
|  | goto cleanup; | 
|  |  | 
|  | /* | 
|  | * We could be more strict here and assert that we read at | 
|  | * least STAT_PARENT_PID_READ_N. My reading of procfs(5) is | 
|  | * that on any modern kernel (at least since 2.6.0 released in | 
|  | * 2003) even if all the mandatory numeric fields were zero'd | 
|  | * out we'd get at least 100 bytes, but let's just check that | 
|  | * we got anything at all and trust the parse_proc_stat() | 
|  | * function to handle its "Bad Kernel?" error checking. | 
|  | */ | 
|  | if (!strbuf_fread(&sb, STAT_PARENT_PID_READ_N, fp)) | 
|  | goto cleanup; | 
|  | if (parse_proc_stat(&sb, name, statppid) < 0) | 
|  | goto cleanup; | 
|  |  | 
|  | ret = 0; | 
|  | cleanup: | 
|  | if (fp) | 
|  | fclose(fp); | 
|  | strbuf_release(&procfs_path); | 
|  | strbuf_release(&sb); | 
|  |  | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | static void push_ancestry_name(struct strvec *names, pid_t pid) | 
|  | { | 
|  | struct strbuf name = STRBUF_INIT; | 
|  | int ppid; | 
|  |  | 
|  | if (stat_parent_pid(pid, &name, &ppid) < 0) | 
|  | goto cleanup; | 
|  |  | 
|  | strvec_push(names, name.buf); | 
|  |  | 
|  | /* | 
|  | * Both errors and reaching the end of the process chain are | 
|  | * reported as fields of 0 by proc(5) | 
|  | */ | 
|  | if (ppid) | 
|  | push_ancestry_name(names, ppid); | 
|  | cleanup: | 
|  | strbuf_release(&name); | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | void trace2_collect_process_info(enum trace2_process_info_reason reason) | 
|  | { | 
|  | struct strvec names = STRVEC_INIT; | 
|  |  | 
|  | if (!trace2_is_enabled()) | 
|  | return; | 
|  |  | 
|  | switch (reason) { | 
|  | case TRACE2_PROCESS_INFO_EXIT: | 
|  | /* | 
|  | * The Windows version of this calls its | 
|  | * get_peak_memory_info() here. We may want to insert | 
|  | * similar process-end statistics here in the future. | 
|  | */ | 
|  | break; | 
|  | case TRACE2_PROCESS_INFO_STARTUP: | 
|  | push_ancestry_name(&names, getppid()); | 
|  |  | 
|  | if (names.nr) | 
|  | trace2_cmd_ancestry(names.v); | 
|  | strvec_clear(&names); | 
|  | break; | 
|  | } | 
|  |  | 
|  | return; | 
|  | } |