1#!/usr/bin/perl -w 2# 3# handlertree.pl 4# ~~~~~~~~~~~~~~ 5# A tool for post-processing the debug output generated by Asio-based programs 6# to print the tree of handlers that resulted in some specified handler ids. 7# Programs write this output to the standard error stream when compiled with 8# the define `BOOST_ASIO_ENABLE_HANDLER_TRACKING'. 9# 10# Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) 11# 12# Distributed under the Boost Software License, Version 1.0. (See accompanying 13# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 14# 15 16use strict; 17 18my %target_handlers = (); 19my @cached_output = (); 20my %outstanding_handlers = (); 21my %running_handlers = (); 22 23#------------------------------------------------------------------------------- 24# Build the initial list of target handlers from the command line arguments. 25 26sub build_initial_target_handlers() 27{ 28 for my $handler (@ARGV) 29 { 30 $target_handlers{$handler} = 1; 31 } 32} 33 34#------------------------------------------------------------------------------- 35# Parse the debugging output and cache the handler tracking lines. 36 37sub parse_debug_output() 38{ 39 while (my $line = <STDIN>) 40 { 41 chomp($line); 42 43 if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/) 44 { 45 push(@cached_output, $line); 46 } 47 } 48} 49 50#------------------------------------------------------------------------------- 51# Iterate over the cached output in revese and build a hash of all target 52# handlers' ancestors. 53 54sub build_target_handler_tree() 55{ 56 my $i = scalar(@cached_output) - 1; 57 while ($i >= 0) 58 { 59 my $line = $cached_output[$i]; 60 61 if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/) 62 { 63 my $action = $2; 64 65 # Handler creation. 66 if ($action =~ /^([0-9]+)\*([0-9]+)$/) 67 { 68 if ($1 ne "0" and exists($target_handlers{$2})) 69 { 70 $target_handlers{$1} = 1; 71 } 72 } 73 } 74 75 --$i; 76 } 77} 78 79#------------------------------------------------------------------------------- 80# Print out all handler tracking records associated with the target handlers. 81 82sub print_target_handler_records() 83{ 84 for my $line (@cached_output) 85 { 86 if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/) 87 { 88 my $action = $2; 89 90 # Handler location. 91 if ($action =~ /^([0-9]+)\^([0-9]+)$/) 92 { 93 print("$line\n") if ($1 eq "0" or exists($target_handlers{$1})) and exists($target_handlers{$2}); 94 } 95 96 # Handler creation. 97 if ($action =~ /^([0-9]+)\*([0-9]+)$/) 98 { 99 print("$1, $2, $line\n") if ($1 eq "0" or exists($target_handlers{$1})) and exists($target_handlers{$2}); 100 } 101 102 # Begin handler invocation. 103 elsif ($action =~ /^>([0-9]+)$/) 104 { 105 print("$line\n") if (exists($target_handlers{$1})); 106 } 107 108 # End handler invocation. 109 elsif ($action =~ /^<([0-9]+)$/) 110 { 111 print("$line\n") if (exists($target_handlers{$1})); 112 } 113 114 # Handler threw exception. 115 elsif ($action =~ /^!([0-9]+)$/) 116 { 117 print("$line\n") if (exists($target_handlers{$1})); 118 } 119 120 # Handler was destroyed without being invoked. 121 elsif ($action =~ /^~([0-9]+)$/) 122 { 123 print("$line\n") if (exists($target_handlers{$1})); 124 } 125 126 # Operation associated with a handler. 127 elsif ($action =~ /^\.([0-9]+)$/) 128 { 129 print("$line\n") if (exists($target_handlers{$1})); 130 } 131 } 132 } 133} 134 135#------------------------------------------------------------------------------- 136 137build_initial_target_handlers(); 138parse_debug_output(); 139build_target_handler_tree(); 140print_target_handler_records(); 141