From 2970cae5436c1e38a98661da3d59c3371051d606 Mon Sep 17 00:00:00 2001 From: Benny Baumann Date: Wed, 30 Sep 2020 23:46:52 +0200 Subject: [PATCH] Handle parsing envID & VPid from process status file Fixes #55 Fixes #192 --- linux/LinuxProcess.c | 11 +++-- linux/LinuxProcess.h | 4 +- linux/LinuxProcessList.c | 93 ++++++++++++++++++++++++++++++++++------ 3 files changed, 90 insertions(+), 18 deletions(-) diff --git a/linux/LinuxProcess.c b/linux/LinuxProcess.c index 373c9ad8..5e661e03 100644 --- a/linux/LinuxProcess.c +++ b/linux/LinuxProcess.c @@ -77,8 +77,8 @@ ProcessFieldData Process_fields[] = { [NLWP] = { .name = "NLWP", .title = "NLWP ", .description = "Number of threads in the process", .flags = 0, }, [TGID] = { .name = "TGID", .title = " TGID ", .description = "Thread group ID (i.e. process ID)", .flags = 0, }, #ifdef HAVE_OPENVZ - [CTID] = { .name = "CTID", .title = " CTID ", .description = "OpenVZ container ID (a.k.a. virtual environment ID)", .flags = PROCESS_FLAG_LINUX_OPENVZ, }, - [VPID] = { .name = "VPID", .title = " VPID ", .description = "OpenVZ process ID", .flags = PROCESS_FLAG_LINUX_OPENVZ, }, + [CTID] = { .name = "CTID", .title = " CTID ", .description = "OpenVZ container ID (a.k.a. virtual environment ID)", .flags = PROCESS_FLAG_LINUX_OPENVZ, }, + [VPID] = { .name = "VPID", .title = " VPID ", .description = "OpenVZ process ID", .flags = PROCESS_FLAG_LINUX_OPENVZ, }, #endif #ifdef HAVE_VSERVER [VXID] = { .name = "VXID", .title = " VXID ", .description = "VServer process ID", .flags = PROCESS_FLAG_LINUX_VSERVER, }, @@ -148,6 +148,9 @@ void Process_delete(Object* cast) { Process_done((Process*)cast); #ifdef HAVE_CGROUP free(this->cgroup); +#endif +#ifdef HAVE_OPENVZ + free(this->ctid); #endif free(this->secattr); free(this->ttyDevice); @@ -253,7 +256,7 @@ void LinuxProcess_writeField(Process* this, RichString* str, ProcessField field) } #endif #ifdef HAVE_OPENVZ - case CTID: xSnprintf(buffer, n, "%7u ", lp->ctid); break; + case CTID: xSnprintf(buffer, n, "%-8s ", lp->ctid ? lp->ctid : ""); break; case VPID: xSnprintf(buffer, n, Process_pidFormat, lp->vpid); break; #endif #ifdef HAVE_VSERVER @@ -351,7 +354,7 @@ long LinuxProcess_compare(const void* v1, const void* v2) { #endif #ifdef HAVE_OPENVZ case CTID: - return (p2->ctid - p1->ctid); + return strcmp(p1->ctid ? p1->ctid : "", p2->ctid ? p2->ctid : ""); case VPID: return (p2->vpid - p1->vpid); #endif diff --git a/linux/LinuxProcess.h b/linux/LinuxProcess.h index 4b2386e9..c1eb0ed5 100644 --- a/linux/LinuxProcess.h +++ b/linux/LinuxProcess.h @@ -122,8 +122,8 @@ typedef struct LinuxProcess_ { double io_rate_write_bps; #endif #ifdef HAVE_OPENVZ - unsigned int ctid; - unsigned int vpid; + char* ctid; + pid_t vpid; #endif #ifdef HAVE_VSERVER unsigned int vxid; diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 2317e1c8..5a32f3dd 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -482,25 +482,94 @@ static bool LinuxProcessList_readSmapsFile(LinuxProcess* process, const char* di static void LinuxProcessList_readOpenVZData(LinuxProcess* process, const char* dirname, const char* name) { if ( (access(PROCDIR "/vz", R_OK) != 0)) { + free(process->ctid); + process->ctid = NULL; process->vpid = process->super.pid; - process->ctid = 0; return; } + char filename[MAX_NAME+1]; - xSnprintf(filename, MAX_NAME, "%s/%s/stat", dirname, name); + xSnprintf(filename, sizeof(filename), "%s/%s/status", dirname, name); FILE* file = fopen(filename, "r"); - if (!file) + if (!file) { + free(process->ctid); + process->ctid = NULL; + process->vpid = process->super.pid; return; - (void)! fscanf(file, - "%*32u %*32s %*1c %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %*32u %*32u %*32u %*32u %*32u " - "%*32u %*32u %32u %32u", - &process->vpid, &process->ctid); + } + + bool foundEnvID = false; + bool foundVPid = false; + char linebuf[256]; + while(fgets(linebuf, sizeof(linebuf), file) != NULL) { + if(strchr(linebuf, '\n') == NULL) { + // Partial line, skip to end of this line + while(fgets(linebuf, sizeof(linebuf), file) != NULL) { + if(strchr(linebuf, '\n') != NULL) { + break; + } + } + continue; + } + + char* name_value_sep = strchr(linebuf, ':'); + if(name_value_sep == NULL) { + continue; + } + + int field; + if(0 == strncasecmp(linebuf, "envID", name_value_sep - linebuf)) { + field = 1; + } else if(0 == strncasecmp(linebuf, "VPid", name_value_sep - linebuf)) { + field = 2; + } else { + continue; + } + + do { + name_value_sep++; + } while(*name_value_sep != '\0' && *name_value_sep <= 32); + + char* value_end = name_value_sep; + + while(*value_end != '\0' && *value_end > 32) { + value_end++; + } + + if(name_value_sep == value_end) { + continue; + } + + *value_end = '\0'; + + switch(field) { + case 1: + foundEnvID = true; + if(0 != strcmp(name_value_sep, process->ctid ? process->ctid : "")) { + free(process->ctid); + process->ctid = xStrdup(name_value_sep); + } + break; + case 2: + foundVPid = true; + process->vpid = strtoul(name_value_sep, NULL, 0); + break; + default: + //Sanity Check: Should never reach here, or the implementation is missing something! + assert(false && "OpenVZ handling: Unimplemented case for field handling reached."); + } + } + fclose(file); + + if(!foundEnvID) { + free(process->ctid); + process->ctid = NULL; + } + + if(!foundVPid) { + process->vpid = process->super.pid; + } } #endif