client, win: when building the global process tree,

don't make a parent->child link if the parent is newer than the child
(this can happen in Win because a process's parentID isn't changed
when its parent exits).
This prevents two potential problems:
- when killing a runaway app, killing unrelated processes too
- incorrect CPU time accounting
This commit is contained in:
davidpanderson 2023-03-17 02:25:53 -07:00
parent 1b721f9583
commit 210f403995
3 changed files with 23 additions and 1 deletions

View File

@ -100,6 +100,25 @@ void find_children(PROC_MAP& pm) {
int parentid = i->second.parentid;
PROC_MAP::iterator j = pm.find(parentid);
if (j == pm.end()) continue; // should never happen
#ifdef _WIN32
// In Windows:
// 1) PIDs are reused, possibly quickly
// 2) if a process creates children and then exits,
// the parentID of the children are not cleared,
// so they may soon refer to an unrelated process.
// (this is horrible design, BTW)
// This can cause problems:
// - when we abort a BOINC app we kill the process and its descendants
// (based on parent ID). These could be unrelated processes.
// - If a BOINC app gets a process ID that is the parentID of
// orphan processes, its CPU time will be computed incorrectly.
// To fix this, don't create a parent/child link
// if the parent was created after the child.
//
if (j->second.create_time.QuadPart > i->second.create_time.QuadPart) {
continue;
}
#endif
j->second.children.push_back(i->first);
}
}

View File

@ -35,9 +35,11 @@ struct PROCINFO {
// running at or below priority of BOINC apps
char command[256];
bool scanned;
double page_fault_rate; // derived by higher-level code
std::vector<int> children;
#ifdef _WIN32
LARGE_INTEGER create_time;
#endif
PROCINFO() {
clear();

View File

@ -97,6 +97,7 @@ int get_procinfo_XP(PROC_MAP& pm) {
p.user_time = ((double) pProcesses->UserTime.QuadPart)/1e7;
p.kernel_time = ((double) pProcesses->KernelTime.QuadPart)/1e7;
p.is_low_priority = (pProcesses->BasePriority <= 4);
p.create_time = pProcesses->CreateTime;
WideCharToMultiByte(CP_ACP, 0,
pProcesses->ProcessName.Buffer,
pProcesses->ProcessName.Length,