--- /dev/null
+#!/usr/bin/env python
+"""
+Copyright (c) 2015-2019 Cray Inc. All Rights Reserved.
+Utility to print unique stack traces
+"""
+
+import re
+import sys
+import StringIO
+import argparse
+from pykdump.API import exec_crash_command
+
+description_short = 'Print stack traces for each task.'
+
+# outer loop indentifies PIDs
+# inner loop looks for # until
+# another PID is found
+def sortInput(swapper, input):
+
+
+ ps = re.compile("^PID:\s+(\d+)\s+TASK:\s+([0-9A-Fa-f]+).*")
+ n = re.compile("^#")
+ swap = re.compile((".*\"swapper/[0-9]+\""))
+ info = dict()
+ PID = ""
+ STK = ""
+ tmp = ""
+
+ # Outer to check for PIDs
+ # this loop never breaks;
+ for line in input:
+ line = line.strip()
+
+ # Inner loop to check for # signs indicating lines we want.
+ # Having two loops allow for the PID and TSK to be associated
+ # with a particular trace.
+ # This loop breaks if a new PID is found (meaning the end of the
+ # current trace) or if there are no more lines available
+ while True:
+ if ps.match(line): break;
+ line = line.strip()
+ if n.match(line):
+ line = line.split()
+ tmp += " ".join([line[2], line[3], line[4]])
+ if len(line) == 6 : tmp += " " + line[5]
+ tmp += '\n\t'
+ line = input.readline()
+ if not line: break
+
+ if tmp :
+ if tmp in info:
+ info[tmp].append((PID,STK))
+ else:
+ info[tmp] = [(PID,STK)]
+
+ m = ps.match(line)
+ if m:
+ PID, STK = m.group(1), m.group(2)
+ tmp = ""
+
+ # if it's swapper line move on
+ # this prevents entry into inner loop
+ if not swapper and swap.match(line):
+ line = input.readline()
+
+ sort = sorted(info.items(), key=lambda info: len(info[1]))
+ return sort
+
+def printRes(sort, printpid, printptr):
+ """
+ Prints out individual stack traces from lowest to highest.
+ """
+ for stack_trace, ptask_list in sort:
+ if printpid and not printptr:
+ print "PID: %s" % (', '.join(p[0] for p in ptask_list))
+ elif printpid and printptr:
+ print "PID, TSK: %s" % (', '.join(p[0] + ': ' + p[1] for p in ptask_list))
+ elif not printpid and printptr:
+ print "TSK: %s" % (', '.join(p[1] for p in ptask_list))
+ print "TASKS: %d" %(len(ptask_list))
+ print "\t%s" %(stack_trace)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+
+ parser.add_argument("-p", "--print-pid",
+ action="store_true", dest="printpid", default=False,
+ help="Print PIDS corresponding to each ST")
+ parser.add_argument("-q", "--print-taskpntr",
+ action="store_true", dest="printptr", default=False,
+ help="Print the task pointers for each ST")
+ parser.add_argument("-s", "--swapper",
+ action="store_true", dest="swapper", default=False,
+ help="Print swapper processes")
+ parser.add_argument("task_select", metavar="task_selection", nargs="*",
+ help="task selection argument (passed to foreach cmd)")
+
+ args = parser.parse_args()
+
+ com = "foreach {ts:s} bt".format(ts=" ".join(args.task_select))
+
+ result = exec_crash_command(com)
+ input = StringIO.StringIO(result)
+ printRes(sortInput(args.swapper, input), args.printpid, args.printptr)
+
+if __name__ == '__main__':
+ main()