Trace.pm 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. # ex:ts=8 sw=4:
  2. # $OpenBSD: Trace.pm,v 1.2 2015/10/30 09:46:45 espie Exp $
  3. #
  4. # Copyright (c) 2015 Marc Espie <espie@openbsd.org>
  5. #
  6. # Permission to use, copy, modify, and distribute this software for any
  7. # purpose with or without fee is hereby granted, provided that the above
  8. # copyright notice and this permission notice appear in all copies.
  9. #
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. package DPB::Trace;
  18. # inspired by Carp::Always
  19. sub trace_message
  20. {
  21. my $msg = '';
  22. my $x = 1;
  23. while (1) {
  24. my @c;
  25. {
  26. package DB;
  27. our @args;
  28. @c = caller($x+1);
  29. }
  30. last if !@c;
  31. $msg .= "$c[3](".
  32. join(', ', map {
  33. if (!defined $_) {
  34. '<undef>';
  35. } else {
  36. my $string;
  37. eval { $string = $_->debug_dump };
  38. if (defined $string) {
  39. "$_($string)";
  40. } else {
  41. $_;
  42. }
  43. }
  44. } @DB::args).
  45. ") called at $c[1] line $c[2]\n";
  46. $x++;
  47. }
  48. return $msg;
  49. }
  50. my ($reporter, $sig, $olddie, $oldwarn, $logfile);
  51. sub setup
  52. {
  53. my $class = shift;
  54. $sig = shift;
  55. $olddie = $SIG{__DIE__};
  56. $oldwarn = $SIG{__WARN__};
  57. $sig->{__WARN__} = sub {
  58. $sig->{__WARN__} = $oldwarn;
  59. my $a = pop @_;
  60. $a =~ s/(.*)( at .*? line .*?)\n$/$1$2/s;
  61. push @_, $a;
  62. my $msg = join("\n", @_, &trace_message);
  63. if (defined $logfile) {
  64. print $logfile $msg;
  65. print $logfile '-'x70, "\n";
  66. }
  67. if (defined $reporter) {
  68. $reporter->myprint($msg);
  69. } else {
  70. warn $msg;
  71. }
  72. };
  73. $sig->{__DIE__} = sub {
  74. die @_ if $^S;
  75. $sig->{__DIE__} = $olddie;
  76. my $a = pop @_;
  77. $a =~ s/(.*)( at .*? line .*?)\n$/$1$2/s;
  78. push @_, $a;
  79. if (defined $reporter) {
  80. $reporter->reset_cursor;
  81. }
  82. my $msg = join("\n", @_, &trace_message);
  83. if (defined $logfile) {
  84. print $logfile $msg;
  85. print $logfile '-'x70, "\n";
  86. }
  87. die $msg;
  88. };
  89. $sig->{INFO} = sub {
  90. print "Trace:\n", &trace_message;
  91. sleep 1;
  92. };
  93. }
  94. END {
  95. $sig->{__DIE__} = $olddie;
  96. $sig->{__WARN__} = $oldwarn;
  97. }
  98. sub set_reporter
  99. {
  100. my $class = shift;
  101. $reporter = shift;
  102. }
  103. sub set_logger
  104. {
  105. my $class = shift;
  106. $logfile = shift;
  107. }
  108. 1;