ScenarioManager::Exec::ProcessUtil Namespace Reference

Classes

struct  ProcessInfo
 A live process as seen by ScanProcesses(). More...
 

Enumerations

enum class  Identity { Matches , Differs , Unverifiable }
 Whether the process behind a pid still is the one we think it is. More...
 

Functions

std::optional< std::string > FindIceConfigArgument (const std::vector< std::string > &arguments)
 
std::vector< std::string > GetProcessArguments (int pid)
 Reads the full argument vector of pid from /proc/<pid>/cmdline.
 
std::string GetProcessName (int pid)
 Reads the name of the executable behind pid (the basename of argv[0]).
 
Identity IdentifyProcess (int pid, const std::string &executableName, const std::string &configPath)
 Checks whether the process with the given pid is still the application it is supposed to be.
 
bool IsAlive (int pid)
 
bool IsZombie (int pid)
 
std::vector< ProcessInfo > ScanProcesses ()
 Walks /proc and returns every process whose argument vector could be read.
 
bool WaitForExit (int pid, std::chrono::milliseconds timeout, std::chrono::milliseconds pollInterval=std::chrono::milliseconds(20))
 Blocks until the process with the given pid has disappeared, at most for timeout.
 

Enumeration Type Documentation

◆ Identity

enum class Identity
strong

Whether the process behind a pid still is the one we think it is.

Enumerator
Matches 

argv says this is the expected executable, and it does not claim a foreign config.

Differs 

argv says this is a different program, or the same program serving a different config.

Unverifiable 

argv could not be read, so nothing can be concluded either way.

A zombie, a process forked but not yet exec'd, and a process we may not inspect all land here.

Definition at line 102 of file ProcessUtil.h.

Function Documentation

◆ FindIceConfigArgument()

std::optional< std::string > FindIceConfigArgument ( const std::vector< std::string > & arguments)
Returns
the value of the --Ice.Config= argument in arguments, if there is one.

Definition at line 207 of file ProcessUtil.cpp.

+ Here is the caller graph for this function:

◆ GetProcessArguments()

std::vector< std::string > GetProcessArguments ( int pid)

Reads the full argument vector of pid from /proc/<pid>/cmdline.

Returns an empty vector when it cannot be read - see GetProcessName() for why that does not imply the process is gone.

Definition at line 141 of file ProcessUtil.cpp.

+ Here is the caller graph for this function:

◆ GetProcessName()

std::string GetProcessName ( int pid)

Reads the name of the executable behind pid (the basename of argv[0]).

Returns an empty string if the name could not be determined. That is not the same as "the process is gone": a process that has been forked but has not reached execve() yet, a zombie and a process we are not allowed to inspect all report an empty name while being very much alive. Callers must use IsAlive() to tell the two cases apart before drawing conclusions about the process' status.

Definition at line 129 of file ProcessUtil.cpp.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IdentifyProcess()

Identity IdentifyProcess ( int pid,
const std::string & executableName,
const std::string & configPath )

Checks whether the process with the given pid is still the application it is supposed to be.

Pids are recycled. Once the process an application was launched as has exited, the kernel is free to hand its pid to something completely unrelated, and from that moment on every conclusion drawn from /proc/<pid> is about a stranger: the application looks alive when it is not, a start is refused because "it is already running", and a stop signals - possibly kills - an innocent process.

configPath is the stronger of the two criteria and catches a pid recycled by another instance of the same binary; it is only applied when the process carries an --Ice.Config at all, since an application started by hand from a shell legitimately has none.

Parameters
executableNamebasename of the application's executable.
configPaththe application's config file; may be empty, in which case only the name is compared.

Definition at line 221 of file ProcessUtil.cpp.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsAlive()

bool IsAlive ( int pid)
Returns
whether a process with the given pid currently exists and has not terminated. pid <= 0 is never alive.

Zombies are deliberately not alive. The whole point of asking is to decide whether there is still a process there to wait for, to signal, or to refuse a start over, and for a zombie the answer to all three is no - waiting for one to disappear runs into the full timeout, and signalling one is silently discarded (kill() even reports success).

Definition at line 108 of file ProcessUtil.cpp.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ IsZombie()

bool IsZombie ( int pid)
Returns
whether the process with the given pid has terminated but has not been reaped yet.

A zombie still occupies its pid and still has a /proc entry, but it is dead: it cannot be signalled, it will never run again, and it disappears only once somebody waits for it. pid <= 0 is never a zombie.

Definition at line 76 of file ProcessUtil.cpp.

+ Here is the caller graph for this function:

◆ ScanProcesses()

std::vector< ProcessInfo > ScanProcesses ( )

Walks /proc and returns every process whose argument vector could be read.

This is the only way to find an application the ScenarioManager did not launch itself (or whose pid it lost), since nothing else ties a running process back to an application. Processes that cannot be read - other users' processes, or ones exiting while we walk - are silently skipped.

The walk costs one open() per process on the machine, so callers are expected to do it for all applications at once rather than per application, and not on every status poll.

Definition at line 172 of file ProcessUtil.cpp.

+ Here is the call graph for this function:

◆ WaitForExit()

bool WaitForExit ( int pid,
std::chrono::milliseconds timeout,
std::chrono::milliseconds pollInterval = std::chrono::milliseconds(20) )

Blocks until the process with the given pid has disappeared, at most for timeout.

Returns
true if the process is gone, false if it was still alive when timeout elapsed.

Definition at line 258 of file ProcessUtil.cpp.

+ Here is the call graph for this function:
+ Here is the caller graph for this function: