<s> import optparse <EOL> import pykd <EOL> import re <EOL> import sys <EOL> import time <EOL> BLACKLIST_LIBS = [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] <EOL> LOG_DEBUG = False <EOL> class log ( object ) : <EOL> @ staticmethod <EOL> def info ( msg , * args ) : <EOL> print >> sys . stderr , msg % args <EOL> @ staticmethod <EOL> def debug ( msg , * args ) : <EOL> if LOG_DEBUG : <EOL> print >> sys . stderr , "<STR_LIT>" + msg % args <EOL> def get_current_stack ( ) : <EOL> call_stack = [ ] <EOL> for line in pykd . dbgCommand ( "<STR_LIT:k>" ) . splitlines ( ) [ <NUM_LIT:1> : ] : <EOL> try : <EOL> _ , ret_addr , sym = line . split ( ) <EOL> _ = int ( ret_addr , <NUM_LIT:16> ) <EOL> except ValueError : <EOL> continue <EOL> call_stack . append ( sym ) <EOL> return call_stack <EOL> def get_addr_list ( ) : <EOL> addr_list = [ ] <EOL> addr_list . append ( pykd . getContext ( ) . ip ( ) ) <EOL> for line in pykd . dbgCommand ( "<STR_LIT:k>" ) . splitlines ( ) [ <NUM_LIT:1> : ] : <EOL> skip = False <EOL> try : <EOL> _ , ret_addr , sym = line . split ( ) <EOL> ret_addr = int ( ret_addr , <NUM_LIT:16> ) <EOL> except ValueError : <EOL> continue <EOL> for noise in BLACKLIST_LIBS : <EOL> if sym . startswith ( noise ) : <EOL> skip = True <EOL> break <EOL> if skip : <EOL> continue <EOL> addr_list . append ( ret_addr ) <EOL> addr_list . pop ( ) <EOL> return addr_list <EOL> def get_thread_run_time ( thread ) : <EOL> thread = thread . split ( ) <EOL> duration = int ( thread [ <NUM_LIT:1> ] ) * <NUM_LIT> <EOL> thread = thread [ - <NUM_LIT:1> ] . split ( '<STR_LIT:.>' ) <EOL> duration += float ( "<STR_LIT>" % thread [ - <NUM_LIT:1> ] ) <EOL> thread = thread [ <NUM_LIT:0> ] . split ( '<STR_LIT::>' ) <EOL> duration += int ( thread [ <NUM_LIT:0> ] ) * <NUM_LIT> <EOL> duration += int ( thread [ <NUM_LIT:1> ] ) * <NUM_LIT> <EOL> duration += int ( thread [ <NUM_LIT:2> ] ) <EOL> return duration <EOL> def get_proc_run_time ( ) : <EOL> duration = <NUM_LIT:0> <EOL> for line in pykd . dbgCommand ( "<STR_LIT>" ) . splitlines ( ) [ - <NUM_LIT:2> : ] : <EOL> line = line . strip ( ) . split ( ) <EOL> duration += int ( line [ <NUM_LIT:2> ] ) * <NUM_LIT> <EOL> line = line [ - <NUM_LIT:1> ] . split ( '<STR_LIT:.>' ) <EOL> duration += float ( "<STR_LIT>" % line [ - <NUM_LIT:1> ] ) <EOL> line = line [ <NUM_LIT:0> ] . split ( '<STR_LIT::>' ) <EOL> duration += int ( line [ <NUM_LIT:0> ] ) * <NUM_LIT> <EOL> duration += int ( line [ <NUM_LIT:1> ] ) * <NUM_LIT> <EOL> duration += int ( line [ <NUM_LIT:2> ] ) <EOL> return duration <EOL> def get_thread_list ( ) : <EOL> return pykd . dbgCommand ( "<STR_LIT>" ) . splitlines ( ) [ <NUM_LIT:2> : ] <EOL> def get_hung_thread ( ) : <EOL> hung_thread = <NUM_LIT:0> <EOL> cur_max = <NUM_LIT:0> <EOL> for thread in get_thread_list ( ) : <EOL> m = re . match ( r"<STR_LIT>" , thread ) <EOL> if not m : <EOL> continue <EOL> run_time = get_thread_run_time ( thread ) <EOL> if run_time > cur_max : <EOL> hung_thread = int ( m . group ( <NUM_LIT:1> ) ) <EOL> cur_max = run_time <EOL> return hung_thread <EOL> def set_thread ( t_id ) : <EOL> pykd . dbgCommand ( "<STR_LIT>" % t_id ) <EOL> def set_bp ( addr , bp_id , count ) : <EOL> pykd . dbgCommand ( "<STR_LIT>" % ( bp_id , addr , count ) ) <EOL> def is_complete ( ) : <EOL> return pykd . dbgCommand ( "<STR_LIT>" ) . find ( "<STR_LIT>" ) != - <NUM_LIT:1> <EOL> def get_bp_hit ( ) : <EOL> tmp_bp = pykd . dbgCommand ( "<STR_LIT>" ) <EOL> if tmp_bp . find ( "<STR_LIT>" ) != - <NUM_LIT:1> : <EOL> return int ( tmp_bp . splitlines ( ) [ <NUM_LIT:0> ] . split ( ) [ - <NUM_LIT:1> ] ) <EOL> return None <EOL> def find_next_sym ( next_bp , prev_bp , timeout ) : <EOL> iters = <NUM_LIT:100> <EOL> found_sym = False <EOL> sample_time = <NUM_LIT:0> <EOL> set_bp ( next_bp , <NUM_LIT:0> , <NUM_LIT:1> ) <EOL> set_bp ( prev_bp , <NUM_LIT:1> , iters ) <EOL> while not is_complete ( ) : <EOL> pykd . go ( ) <EOL> curr_bp = get_bp_hit ( ) <EOL> target_time = get_proc_run_time ( ) <EOL> log . debug ( "<STR_LIT>" , target_time ) <EOL> if curr_bp == <NUM_LIT:1> : <EOL> if target_time >= timeout : <EOL> break <EOL> iter_duration = target_time - sample_time <EOL> if iter_duration < <NUM_LIT:0.5> : <EOL> if iters < <NUM_LIT> : <EOL> iters *= <NUM_LIT:2> <EOL> log . debug ( "<STR_LIT>" , iter_duration , iters ) <EOL> elif iter_duration >= <NUM_LIT:0.5> and iter_duration < <NUM_LIT> : <EOL> iters += <NUM_LIT:100> <EOL> log . debug ( "<STR_LIT>" , iter_duration , iters ) <EOL> set_bp ( prev_bp , <NUM_LIT:1> , iters ) <EOL> elif curr_bp == <NUM_LIT:0> : <EOL> found_sym = True <EOL> break <EOL> else : <EOL> log . debug ( "<STR_LIT>" ) <EOL> if pykd . dbgCommand ( "<STR_LIT>" ) . find ( "<STR_LIT>" ) != - <NUM_LIT:1> : <EOL> raise RuntimeError ( "<STR_LIT>" ) <EOL> sample_time = target_time <EOL> pykd . removeBp ( <NUM_LIT:1> ) <EOL> pykd . removeBp ( <NUM_LIT:0> ) <EOL> return found_sym <EOL> def filter_noise ( call_stack ) : <EOL> strip_count = <NUM_LIT:0> <EOL> for line in call_stack : <EOL> for lib in BLACKLIST_LIBS : <EOL> if line . startswith ( lib ) : <EOL> line = None <EOL> break <EOL> if line is not None and line . find ( "<STR_LIT:<>" ) == - <NUM_LIT:1> and line . find ( "<STR_LIT:[>" ) == - <NUM_LIT:1> : <EOL> break <EOL> strip_count += <NUM_LIT:1> <EOL> return call_stack [ strip_count : ] <EOL> def main ( timeout ) : <EOL> run_time = time . time ( ) <EOL> log . debug ( "<STR_LIT>" , timeout ) <EOL> log . debug ( "<STR_LIT>" ) <EOL> set_thread ( get_hung_thread ( ) ) <EOL> log . debug ( "<STR_LIT>" ) <EOL> addrs = get_addr_list ( ) <EOL> while len ( addrs ) > <NUM_LIT:1> : <EOL> log . debug ( "<STR_LIT>" , len ( addrs ) ) <EOL> if not find_next_sym ( addrs [ <NUM_LIT:1> ] , addrs [ <NUM_LIT:0> ] , timeout ) and not is_complete ( ) : <EOL> log . debug ( "<STR_LIT>" ) <EOL> break <EOL> if get_proc_run_time ( ) >= timeout : <EOL> log . debug ( "<STR_LIT>" ) <EOL> break <EOL> addrs . pop ( <NUM_LIT:0> ) <EOL> if is_complete ( ) : <EOL> log . info ( "<STR_LIT>" ) <EOL> addrs = list ( ) <EOL> log . info ( "<STR_LIT:*>" * <NUM_LIT> ) <EOL> if addrs : <EOL> for line in filter_noise ( get_current_stack ( ) ) : <EOL> log . info ( "<STR_LIT>" , line ) <EOL> else : <EOL> log . info ( "<STR_LIT>" ) <EOL> log . info ( "<STR_LIT:*>" * <NUM_LIT> ) <EOL> log . info ( "<STR_LIT>" ) <EOL> log . info ( "<STR_LIT>" , time . time ( ) - run_time ) <EOL> log . info ( "<STR_LIT>" , get_proc_run_time ( ) ) <EOL> log . info ( "<STR_LIT>" , get_thread_run_time ( get_thread_list ( ) [ get_hung_thread ( ) ] ) ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> opter = optparse . OptionParser ( ) <EOL> opter . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , default = <NUM_LIT> , type = "<STR_LIT:int>" , <EOL> help = "<STR_LIT>" ) <EOL> opter . add_option ( "<STR_LIT>" , "<STR_LIT>" , dest = "<STR_LIT>" , action = "<STR_LIT:store_true>" , default = False , <EOL> help = "<STR_LIT>" ) <EOL> ( opts , args ) = opter . parse_args ( ) <EOL> LOG_DEBUG = opts . verbose <EOL> main ( opts . timeout ) </s>
