def __init__(self): self._statProcessTree = StatProcessTree() self._unfinishedResult = {} self._futexHolderPid = {} self._futexWaiterPids = defaultdict(list) self._pluginOptionDict = {} self._outputFile = sys.stdout
def __init__(self): self._statProcessTree = StatProcessTree() self._lastSyscallStore = defaultdict(deque) self._lastSyscallTime = {}
class StatLastSyscall(StatBase): """ Find the last few unfinished syscall of process """ def __init__(self): self._statProcessTree = StatProcessTree() self._lastSyscallStore = defaultdict(deque) self._lastSyscallTime = {} def isOperational(self, straceOptions): self._straceOptions = straceOptions return True def getSyscallHooks(self): if self._straceOptions["havePid"]: return self._statProcessTree.getSyscallHooks() else: return None def getRawSyscallHooks(self): return {"ALL": self.funcHandleALLSyscall} def _reconstructStraceLine(self, result): # recontruct the strace line if self._straceOptions["haveTime"]: syscallLine = result["startTime"].strftime("%H:%M:%S.%f") + " " else: syscallLine = "" syscallLine += "{0} (".format(result["syscall"]) + ", ".join( [str(a) for a in result["args"]]) if result["type"] == "unfinished": syscallLine += " <unfinished ...>" else: syscallLine += ")" # pad some space before return value if it is too short # in order to match to original strace output syscallLine = "{0:<39} = {1}".format(syscallLine, result["return"]) return syscallLine def funcHandleALLSyscall(self, result): if self._straceOptions["havePid"]: pid = result["pid"] else: pid = 0 # store the last syscall time if self._straceOptions["haveTime"]: syscallTime = result["startTime"] self._lastSyscallTime[pid] = syscallTime self._latestTime = syscallTime self._lastSyscallStore[pid].append(result) if len(self._lastSyscallStore[pid]) > 3: # store last 3 syscalls self._lastSyscallStore[pid].popleft() def printOutput(self): for pid, syscallList in self._lastSyscallStore.iteritems(): if self._straceOptions["haveTime"]: waitTime = self._latestTime - self._lastSyscallTime[pid] else: waitTime = "" # Ignore all the exited process if "exit" not in syscallList[-1]["syscall"]: #print pid, self._statProcessTree.getProcessExecName(pid), waitTime #for syscallResult in syscallList: # print " ", self._reconstructStraceLine(syscallResult) print pid, waitTime, self._reconstructStraceLine( syscallList[-1])
class StatLastSyscall(StatBase): """ Find the last few unfinished syscall of process """ def __init__(self): self._statProcessTree = StatProcessTree() self._lastSyscallStore = defaultdict(deque) self._lastSyscallTime = {} def isOperational(self, straceOptions): self._straceOptions = straceOptions return True def getSyscallHooks(self): if self._straceOptions["havePid"]: return self._statProcessTree.getSyscallHooks() else: return None def getRawSyscallHooks(self): return {"ALL": self.funcHandleALLSyscall} def _reconstructStraceLine(self, result): # recontruct the strace line if self._straceOptions["haveTime"]: syscallLine = result["startTime"].strftime("%H:%M:%S.%f") + " " else: syscallLine = "" syscallLine += "{0} (".format(result["syscall"]) + ", ".join([str(a) for a in result["args"]]) if result["type"] == "unfinished": syscallLine += " <unfinished ...>" else: syscallLine += ")" # pad some space before return value if it is too short # in order to match to original strace output syscallLine = "{0:<39} = {1}".format(syscallLine, result["return"]) return syscallLine def funcHandleALLSyscall(self, result): if self._straceOptions["havePid"]: pid = result["pid"] else: pid = 0 # store the last syscall time if self._straceOptions["haveTime"]: syscallTime = result["startTime"] self._lastSyscallTime[pid] = syscallTime self._latestTime = syscallTime self._lastSyscallStore[pid].append(result) if len(self._lastSyscallStore[pid]) > 3: # store last 3 syscalls self._lastSyscallStore[pid].popleft() def printOutput(self): for pid, syscallList in self._lastSyscallStore.iteritems(): if self._straceOptions["haveTime"]: waitTime = self._latestTime - self._lastSyscallTime[pid] else: waitTime = "" # Ignore all the exited process if "exit" not in syscallList[-1]["syscall"]: #print pid, self._statProcessTree.getProcessExecName(pid), waitTime #for syscallResult in syscallList: # print " ", self._reconstructStraceLine(syscallResult) print pid, waitTime, self._reconstructStraceLine(syscallList[-1])
def __init__(self): self._statProcessTree = StatProcessTree() self._unfinishedResult = {} self._futexHolderPid = {} self._futexWaiterPids = defaultdict(list)
class StatFutex(StatBase): """ Get futex related info """ def __init__(self): self._statProcessTree = StatProcessTree() self._unfinishedResult = {} self._futexHolderPid = {} self._futexWaiterPids = defaultdict(list) def isOperational(self, straceOptions): self._straceOptions = straceOptions return True def getSyscallHooks(self): if self._straceOptions["havePid"]: return self._statProcessTree.getSyscallHooks() else: return None def getRawSyscallHooks(self): if self._straceOptions["havePid"]: return {"futex": self.funcHandleFutexSyscall} return None def funcHandleFutexSyscall(self, result): #print result pid = result["pid"] syscallType = result["type"] timeStr = result["startTime"].time() if syscallType == "resumed": # if this is a resume syscall, combine it with last unfinished syscall of this pid lastResult = self._unfinishedResult[pid] lastResult["return"] = result["return"] lastResult["args"].append(result["args"]) lastResult["type"] = "completed" result = lastResult elif syscallType == "unfinished": self._unfinishedResult[pid] = result futexAddress = result["args"][0] futexOp = result["args"][1] if "FUTEX_WAIT" in futexOp: if syscallType == "unfinished": # wait on a futex # add myself in waiter list self._futexWaiterPids[futexAddress].append(pid) print "{0} pid:{1} wait futex:{2}, current holder:{3}, waiting list:{4}".format( timeStr, pid, futexAddress, self._futexHolderPid[futexAddress] if futexAddress in self._futexHolderPid else "Unknown", self._futexWaiterPids[futexAddress]) else: # completed or resumed = being wake up or timeout # remove myself from futexWaiterPids if futexAddress in self._futexWaiterPids: if pid in self._futexWaiterPids[futexAddress]: self._futexWaiterPids[futexAddress].remove(pid) returnValue = result["return"] if int(returnValue) == 0: # being wake up self._futexHolderPid[futexAddress] = pid # I am the holder now print "{0} pid:{1} hold futex:{2}, waiting list:{3}".format( timeStr, pid, futexAddress, self._futexWaiterPids[futexAddress]) else: # timeout print "{0} pid:{1} timeout futex:{2}".format(timeStr, pid, futexAddress) #TODO: many different cases in man page if "FUTEX_WAKE" in futexOp: self._futexHolderPid[futexAddress] = None print "{0} pid:{1} release futex:{2}, waiting list:{3}".format( timeStr, pid, futexAddress, self._futexWaiterPids[futexAddress]) def printOutput(self): futexAddressSet = set(self._futexHolderPid.keys() + self._futexWaiterPids.keys()) print "Futex Address,Holder,Waiters" for addr in futexAddressSet: print "{0},{1},{2}".format(addr, self._futexHolderPid[addr] if addr in self._futexHolderPid else "Unknown", self._futexWaiterPids[addr])