def getPwd(pid): """ Provices the working directory of the given process. This raises an IOError if it can't be determined. Arguments: pid - pid of the process """ if not pid: raise IOError("we couldn't get the pid") elif pid in PWD_CACHE: return PWD_CACHE[pid] # try fetching via the proc contents if available if procTools.isProcAvailable(): try: pwd = procTools.getPwd(pid) PWD_CACHE[pid] = pwd return pwd except IOError: pass # fall back to pwdx elif os.uname()[0] in ("Darwin", "FreeBSD", "OpenBSD"): # BSD neither useres the above proc info nor does it have pwdx. Use lsof to # determine this instead: # https://trac.torproject.org/projects/tor/ticket/4236 # # ~$ lsof -a -p 75717 -d cwd -Fn # p75717 # n/Users/atagar/tor/src/or try: results = call("lsof -a -p %s -d cwd -Fn" % pid) if results and len(results) == 2 and results[1].startswith("n/"): pwd = results[1][1:].strip() PWD_CACHE[pid] = pwd return pwd except IOError, exc: pass try: # pwdx results are of the form: # 3799: /home/atagar # 5839: No such process results = call("pwdx %s" % pid) if not results: raise IOError("pwdx didn't return any results") elif results[0].endswith("No such process"): raise IOError("pwdx reported no process for pid " + pid) elif len(results) != 1 or results[0].count(" ") != 1: raise IOError("we got unexpected output from pwdx") else: pwd = results[0][results[0].find(" ") + 1:].strip() PWD_CACHE[pid] = pwd return pwd except IOError, exc: raise IOError("the pwdx call failed: " + str(exc))
def __init__(self, processPid, resolveRate): """ Initializes a new resolver daemon. When no longer needed it's suggested that this is stopped. Arguments: processPid - pid of the process being tracked resolveRate - time between resolving resource usage, resolution is disabled if zero """ threading.Thread.__init__(self) self.setDaemon(True) self.processPid = processPid self.resolveRate = resolveRate self.cpuSampling = 0.0 # latest cpu usage sampling self.cpuAvg = 0.0 # total average cpu usage self.memUsage = 0 # last sampled memory usage in bytes self.memUsagePercentage = 0.0 # percentage cpu usage # resolves usage via proc results if true, ps otherwise self._useProc = procTools.isProcAvailable() # used to get the deltas when querying cpu time self._lastCpuTotal = 0 self.lastLookup = -1 self._halt = False # terminates thread if true self._valLock = threading.RLock() self._cond = threading.Condition() # used for pausing the thread # number of successful calls we've made self._runCount = 0 # sequential times we've failed with this method of resolution self._failureCount = 0
def getPwd(pid): """ Provices the working directory of the given process. This raises an IOError if it can't be determined. Arguments: pid - pid of the process """ if not pid: raise IOError("we couldn't get the pid") elif pid in PWD_CACHE: return PWD_CACHE[pid] # try fetching via the proc contents if available if procTools.isProcAvailable(): try: pwd = procTools.getPwd(pid) PWD_CACHE[pid] = pwd return pwd except IOError: pass # fall back to pwdx try: # pwdx results are of the form: # 3799: /home/atagar # 5839: No such process results = call("pwdx %s" % pid) if not results: raise IOError("pwdx didn't return any results") elif results[0].endswith("No such process"): raise IOError("pwdx reported no process for pid " + pid) elif len(results) != 1 or results[0].count(" ") != 1: raise IOError("we got unexpected output from pwdx") else: pwd = results[0][results[0].find(" ") + 1:].strip() PWD_CACHE[pid] = pwd return pwd except IOError, exc: raise IOError("the pwdx call failed: " + str(exc))
def getSystemResolvers(osType = None): """ Provides the types of connection resolvers available on this operating system. Arguments: osType - operating system type, fetched from the os module if undefined """ if osType == None: osType = os.uname()[0] if osType == "FreeBSD": resolvers = [Resolver.BSD_SOCKSTAT, Resolver.BSD_PROCSTAT, Resolver.LSOF] elif osType == "Darwin": resolvers = [Resolver.LSOF] else: resolvers = [Resolver.NETSTAT, Resolver.SOCKSTAT, Resolver.LSOF, Resolver.SS] # proc resolution, by far, outperforms the others so defaults to this is able if procTools.isProcAvailable(): resolvers = [Resolver.PROC] + resolvers return resolvers
def getProcessName(pid, default = None, cacheFailure = True): """ Provides the name associated with the given process id. This isn't available on all platforms. Arguments: pid - process id for the process being returned default - result if the process name can't be retrieved (raises an IOError on failure instead if undefined) cacheFailure - if the lookup fails and there's a default then caches the default value to prevent further lookups """ if pid in PROCESS_NAME_CACHE: return PROCESS_NAME_CACHE[pid] processName, raisedExc = "", None # fetch it from proc contents if available if procTools.isProcAvailable(): try: processName = procTools.getStats(pid, procTools.Stat.COMMAND)[0] except IOError, exc: raisedExc = exc
def getProcessName(pid, default=None, cacheFailure=True): """ Provides the name associated with the given process id. This isn't available on all platforms. Arguments: pid - process id for the process being returned default - result if the process name can't be retrieved (raises an IOError on failure instead if undefined) cacheFailure - if the lookup fails and there's a default then caches the default value to prevent further lookups """ if pid in PROCESS_NAME_CACHE: return PROCESS_NAME_CACHE[pid] processName, raisedExc = "", None # fetch it from proc contents if available if procTools.isProcAvailable(): try: processName = procTools.getStats(pid, procTools.Stat.COMMAND)[0] except IOError, exc: raisedExc = exc