• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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