From 1c39d47784216a63be5ebba3808477d97f1b1e41 Mon Sep 17 00:00:00 2001 From: Christopher Kohlhoff Date: Mon, 22 Jun 2020 20:48:55 +1000 Subject: [PATCH] Add handlertree.pl tool. The handlertree.pl script filters handler tracking output to include only those events in the tree that produced the nominated handlers. For example, to filter the output to include only the events associated with handlers 123, 456, and their predecessors: cat output.txt | perl handlertree.pl 123 456 or: perl handlertree.pl 123 456 < output.txt This script may be combined with handerlive.pl and handlerviz.pl to produce a graph of the "live" asynchronous operation chains. For example: cat output.txt | perl handlertree.pl `perl handlerlive.pl output.txt` | perl handlerviz.pl | dot -Tsvg > output.svg --- tools/handlertree.pl | 140 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 tools/handlertree.pl diff --git a/tools/handlertree.pl b/tools/handlertree.pl new file mode 100644 index 0000000000..ff5c06b1d9 --- /dev/null +++ b/tools/handlertree.pl @@ -0,0 +1,140 @@ +#!/usr/bin/perl -w +# +# handlertree.pl +# ~~~~~~~~~~~~~~ +# A tool for post-processing the debug output generated by Asio-based programs +# to print the tree of handlers that resulted in some specified handler ids. +# Programs write this output to the standard error stream when compiled with +# the define `BOOST_ASIO_ENABLE_HANDLER_TRACKING'. +# +# Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# + +use strict; + +my %target_handlers = (); +my @cached_output = (); +my %outstanding_handlers = (); +my %running_handlers = (); + +#------------------------------------------------------------------------------- +# Build the initial list of target handlers from the command line arguments. + +sub build_initial_target_handlers() +{ + for my $handler (@ARGV) + { + $target_handlers{$handler} = 1; + } +} + +#------------------------------------------------------------------------------- +# Parse the debugging output and cache the handler tracking lines. + +sub parse_debug_output() +{ + while (my $line = ) + { + chomp($line); + + if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/) + { + push(@cached_output, $line); + } + } +} + +#------------------------------------------------------------------------------- +# Iterate over the cached output in revese and build a hash of all target +# handlers' ancestors. + +sub build_target_handler_tree() +{ + my $i = scalar(@cached_output) - 1; + while ($i >= 0) + { + my $line = $cached_output[$i]; + + if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/) + { + my $action = $2; + + # Handler creation. + if ($action =~ /^([0-9]+)\*([0-9]+)$/) + { + if ($1 ne "0" and exists($target_handlers{$2})) + { + $target_handlers{$1} = 1; + } + } + } + + --$i; + } +} + +#------------------------------------------------------------------------------- +# Print out all handler tracking records associated with the target handlers. + +sub print_target_handler_records() +{ + for my $line (@cached_output) + { + if ($line =~ /\@asio\|([^|]*)\|([^|]*)\|(.*)$/) + { + my $action = $2; + + # Handler location. + if ($action =~ /^([0-9]+)\^([0-9]+)$/) + { + print("$line\n") if ($1 eq "0" or exists($target_handlers{$1})) and exists($target_handlers{$2}); + } + + # Handler creation. + if ($action =~ /^([0-9]+)\*([0-9]+)$/) + { + print("$1, $2, $line\n") if ($1 eq "0" or exists($target_handlers{$1})) and exists($target_handlers{$2}); + } + + # Begin handler invocation. + elsif ($action =~ /^>([0-9]+)$/) + { + print("$line\n") if (exists($target_handlers{$1})); + } + + # End handler invocation. + elsif ($action =~ /^<([0-9]+)$/) + { + print("$line\n") if (exists($target_handlers{$1})); + } + + # Handler threw exception. + elsif ($action =~ /^!([0-9]+)$/) + { + print("$line\n") if (exists($target_handlers{$1})); + } + + # Handler was destroyed without being invoked. + elsif ($action =~ /^~([0-9]+)$/) + { + print("$line\n") if (exists($target_handlers{$1})); + } + + # Operation associated with a handler. + elsif ($action =~ /^\.([0-9]+)$/) + { + print("$line\n") if (exists($target_handlers{$1})); + } + } + } +} + +#------------------------------------------------------------------------------- + +build_initial_target_handlers(); +parse_debug_output(); +build_target_handler_tree(); +print_target_handler_records();