33#include <Psapi.h>
44#include <tlHelp32.h>
55
6+ #define NR_PIDS_LIMIT 42
7+
68/*
79 * Find the process data for the given PID in the given snapshot
810 * and update the PROCESSENTRY32 data.
@@ -21,13 +23,17 @@ static int find_pid(DWORD pid, HANDLE hSnapshot, PROCESSENTRY32 *pe32)
2123}
2224
2325/*
24- * Accumulate JSON array:
26+ * Accumulate JSON array of our parent processes :
2527 * [
2628 * exe-name-parent,
2729 * exe-name-grand-parent,
2830 * ...
2931 * ]
3032 *
33+ * We artificially limit this to NR_PIDS_LIMIT to quickly guard against cycles
34+ * in the parent PIDs without a lot of fuss and because we just want some
35+ * context and don't need an absolute answer.
36+ *
3137 * Note: we only report the filename of the process executable; the
3238 * only way to get its full pathname is to use OpenProcess()
3339 * and GetModuleFileNameEx() or QueryfullProcessImageName()
@@ -38,16 +44,28 @@ static void get_processes(struct json_writer *jw, HANDLE hSnapshot)
3844{
3945 PROCESSENTRY32 pe32 ;
4046 DWORD pid ;
47+ DWORD pid_list [NR_PIDS_LIMIT ];
48+ int k , nr_pids = 0 ;
4149
4250 pid = GetCurrentProcessId ();
51+ while (find_pid (pid , hSnapshot , & pe32 )) {
52+ /* Only report parents. Omit self from the JSON output. */
53+ if (nr_pids )
54+ jw_array_string (jw , pe32 .szExeFile );
4355
44- /* We only want parent processes, so skip self. */
45- if (!find_pid (pid , hSnapshot , & pe32 ))
46- return ;
47- pid = pe32 .th32ParentProcessID ;
56+ /* Check for cycle in snapshot. (Yes, it happened.) */
57+ for (k = 0 ; k < nr_pids ; k ++ )
58+ if (pid == pid_list [k ]) {
59+ jw_array_string (jw , "(cycle)" );
60+ return ;
61+ }
4862
49- while (find_pid (pid , hSnapshot , & pe32 )) {
50- jw_array_string (jw , pe32 .szExeFile );
63+ if (nr_pids == NR_PIDS_LIMIT ) {
64+ jw_array_string (jw , "(truncated)" );
65+ return ;
66+ }
67+
68+ pid_list [nr_pids ++ ] = pid ;
5169
5270 pid = pe32 .th32ParentProcessID ;
5371 }
0 commit comments