Skip to content

Commit

Permalink
Add handlertree.pl tool.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
chriskohlhoff committed Jun 22, 2020
1 parent bc62166 commit 1c39d47
Showing 1 changed file with 140 additions and 0 deletions.
140 changes: 140 additions & 0 deletions tools/handlertree.pl
Original file line number Diff line number Diff line change
@@ -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 = <STDIN>)
{
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();

0 comments on commit 1c39d47

Please sign in to comment.