| File | /usr/share/perl/5.10/CGI/Carp.pm |
| Statements Executed | 4227 |
| Total Time | 0.016725 seconds |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 109 | 1 | 1 | 8.26ms | 10.5ms | CGI::Carp::stamp |
| 110 | 2 | 1 | 2.79ms | 5.44ms | CGI::Carp::id |
| 109 | 1 | 1 | 1.97ms | 1.97ms | CGI::Carp::realwarn |
| 1 | 1 | 1 | 26µs | 26µs | CGI::Carp::realdie |
| 1 | 1 | 1 | 24µs | 24µs | CGI::Carp::ineval |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::BEGIN |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::_longmess |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::_warn |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::carp |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::carpout |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::cluck |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::confess |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::croak |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::die |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::fatalsToBrowser |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::import |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::set_die_handler |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::set_message |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::set_progname |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::to_filehandle |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::warn |
| 0 | 0 | 0 | 0s | 0s | CGI::Carp::warningsToBrowser |
| Line | Stmts. | Exclusive Time | Avg. | Code |
|---|---|---|---|---|
| 1 | package CGI::Carp; | |||
| 2 | ||||
| 3 | =head1 NAME | |||
| 4 | ||||
| 5 | B<CGI::Carp> - CGI routines for writing to the HTTPD (or other) error log | |||
| 6 | ||||
| 7 | =head1 SYNOPSIS | |||
| 8 | ||||
| 9 | use CGI::Carp; | |||
| 10 | ||||
| 11 | croak "We're outta here!"; | |||
| 12 | confess "It was my fault: $!"; | |||
| 13 | carp "It was your fault!"; | |||
| 14 | warn "I'm confused"; | |||
| 15 | die "I'm dying.\n"; | |||
| 16 | ||||
| 17 | use CGI::Carp qw(cluck); | |||
| 18 | cluck "I wouldn't do that if I were you"; | |||
| 19 | ||||
| 20 | use CGI::Carp qw(fatalsToBrowser); | |||
| 21 | die "Fatal error messages are now sent to browser"; | |||
| 22 | ||||
| 23 | =head1 DESCRIPTION | |||
| 24 | ||||
| 25 | CGI scripts have a nasty habit of leaving warning messages in the error | |||
| 26 | logs that are neither time stamped nor fully identified. Tracking down | |||
| 27 | the script that caused the error is a pain. This fixes that. Replace | |||
| 28 | the usual | |||
| 29 | ||||
| 30 | use Carp; | |||
| 31 | ||||
| 32 | with | |||
| 33 | ||||
| 34 | use CGI::Carp | |||
| 35 | ||||
| 36 | And the standard warn(), die (), croak(), confess() and carp() calls | |||
| 37 | will automagically be replaced with functions that write out nicely | |||
| 38 | time-stamped messages to the HTTP server error log. | |||
| 39 | ||||
| 40 | For example: | |||
| 41 | ||||
| 42 | [Fri Nov 17 21:40:43 1995] test.pl: I'm confused at test.pl line 3. | |||
| 43 | [Fri Nov 17 21:40:43 1995] test.pl: Got an error message: Permission denied. | |||
| 44 | [Fri Nov 17 21:40:43 1995] test.pl: I'm dying. | |||
| 45 | ||||
| 46 | =head1 REDIRECTING ERROR MESSAGES | |||
| 47 | ||||
| 48 | By default, error messages are sent to STDERR. Most HTTPD servers | |||
| 49 | direct STDERR to the server's error log. Some applications may wish | |||
| 50 | to keep private error logs, distinct from the server's error log, or | |||
| 51 | they may wish to direct error messages to STDOUT so that the browser | |||
| 52 | will receive them. | |||
| 53 | ||||
| 54 | The C<carpout()> function is provided for this purpose. Since | |||
| 55 | carpout() is not exported by default, you must import it explicitly by | |||
| 56 | saying | |||
| 57 | ||||
| 58 | use CGI::Carp qw(carpout); | |||
| 59 | ||||
| 60 | The carpout() function requires one argument, which should be a | |||
| 61 | reference to an open filehandle for writing errors. It should be | |||
| 62 | called in a C<BEGIN> block at the top of the CGI application so that | |||
| 63 | compiler errors will be caught. Example: | |||
| 64 | ||||
| 65 | BEGIN { | |||
| 66 | use CGI::Carp qw(carpout); | |||
| 67 | open(LOG, ">>/usr/local/cgi-logs/mycgi-log") or | |||
| 68 | die("Unable to open mycgi-log: $!\n"); | |||
| 69 | carpout(LOG); | |||
| 70 | } | |||
| 71 | ||||
| 72 | carpout() does not handle file locking on the log for you at this point. | |||
| 73 | ||||
| 74 | The real STDERR is not closed -- it is moved to CGI::Carp::SAVEERR. Some | |||
| 75 | servers, when dealing with CGI scripts, close their connection to the | |||
| 76 | browser when the script closes STDOUT and STDERR. CGI::Carp::SAVEERR is there to | |||
| 77 | prevent this from happening prematurely. | |||
| 78 | ||||
| 79 | You can pass filehandles to carpout() in a variety of ways. The "correct" | |||
| 80 | way according to Tom Christiansen is to pass a reference to a filehandle | |||
| 81 | GLOB: | |||
| 82 | ||||
| 83 | carpout(\*LOG); | |||
| 84 | ||||
| 85 | This looks weird to mere mortals however, so the following syntaxes are | |||
| 86 | accepted as well: | |||
| 87 | ||||
| 88 | carpout(LOG); | |||
| 89 | carpout(main::LOG); | |||
| 90 | carpout(main'LOG); | |||
| 91 | carpout(\LOG); | |||
| 92 | carpout(\'main::LOG'); | |||
| 93 | ||||
| 94 | ... and so on | |||
| 95 | ||||
| 96 | FileHandle and other objects work as well. | |||
| 97 | ||||
| 98 | Use of carpout() is not great for performance, so it is recommended | |||
| 99 | for debugging purposes or for moderate-use applications. A future | |||
| 100 | version of this module may delay redirecting STDERR until one of the | |||
| 101 | CGI::Carp methods is called to prevent the performance hit. | |||
| 102 | ||||
| 103 | =head1 MAKING PERL ERRORS APPEAR IN THE BROWSER WINDOW | |||
| 104 | ||||
| 105 | If you want to send fatal (die, confess) errors to the browser, ask to | |||
| 106 | import the special "fatalsToBrowser" subroutine: | |||
| 107 | ||||
| 108 | use CGI::Carp qw(fatalsToBrowser); | |||
| 109 | die "Bad error here"; | |||
| 110 | ||||
| 111 | Fatal errors will now be echoed to the browser as well as to the log. CGI::Carp | |||
| 112 | arranges to send a minimal HTTP header to the browser so that even errors that | |||
| 113 | occur in the early compile phase will be seen. | |||
| 114 | Nonfatal errors will still be directed to the log file only (unless redirected | |||
| 115 | with carpout). | |||
| 116 | ||||
| 117 | Note that fatalsToBrowser does B<not> work with mod_perl version 2.0 | |||
| 118 | and higher. | |||
| 119 | ||||
| 120 | =head2 Changing the default message | |||
| 121 | ||||
| 122 | By default, the software error message is followed by a note to | |||
| 123 | contact the Webmaster by e-mail with the time and date of the error. | |||
| 124 | If this message is not to your liking, you can change it using the | |||
| 125 | set_message() routine. This is not imported by default; you should | |||
| 126 | import it on the use() line: | |||
| 127 | ||||
| 128 | use CGI::Carp qw(fatalsToBrowser set_message); | |||
| 129 | set_message("It's not a bug, it's a feature!"); | |||
| 130 | ||||
| 131 | You may also pass in a code reference in order to create a custom | |||
| 132 | error message. At run time, your code will be called with the text | |||
| 133 | of the error message that caused the script to die. Example: | |||
| 134 | ||||
| 135 | use CGI::Carp qw(fatalsToBrowser set_message); | |||
| 136 | BEGIN { | |||
| 137 | sub handle_errors { | |||
| 138 | my $msg = shift; | |||
| 139 | print "<h1>Oh gosh</h1>"; | |||
| 140 | print "<p>Got an error: $msg</p>"; | |||
| 141 | } | |||
| 142 | set_message(\&handle_errors); | |||
| 143 | } | |||
| 144 | ||||
| 145 | In order to correctly intercept compile-time errors, you should call | |||
| 146 | set_message() from within a BEGIN{} block. | |||
| 147 | ||||
| 148 | =head1 DOING MORE THAN PRINTING A MESSAGE IN THE EVENT OF PERL ERRORS | |||
| 149 | ||||
| 150 | If fatalsToBrowser in conjunction with set_message does not provide | |||
| 151 | you with all of the functionality you need, you can go one step | |||
| 152 | further by specifying a function to be executed any time a script | |||
| 153 | calls "die", has a syntax error, or dies unexpectedly at runtime | |||
| 154 | with a line like "undef->explode();". | |||
| 155 | ||||
| 156 | use CGI::Carp qw(set_die_handler); | |||
| 157 | BEGIN { | |||
| 158 | sub handle_errors { | |||
| 159 | my $msg = shift; | |||
| 160 | print "content-type: text/html\n\n"; | |||
| 161 | print "<h1>Oh gosh</h1>"; | |||
| 162 | print "<p>Got an error: $msg</p>"; | |||
| 163 | ||||
| 164 | #proceed to send an email to a system administrator, | |||
| 165 | #write a detailed message to the browser and/or a log, | |||
| 166 | #etc.... | |||
| 167 | } | |||
| 168 | set_die_handler(\&handle_errors); | |||
| 169 | } | |||
| 170 | ||||
| 171 | Notice that if you use set_die_handler(), you must handle sending | |||
| 172 | HTML headers to the browser yourself if you are printing a message. | |||
| 173 | ||||
| 174 | If you use set_die_handler(), you will most likely interfere with | |||
| 175 | the behavior of fatalsToBrowser, so you must use this or that, not | |||
| 176 | both. | |||
| 177 | ||||
| 178 | Using set_die_handler() sets SIG{__DIE__} (as does fatalsToBrowser), | |||
| 179 | and there is only one SIG{__DIE__}. This means that if you are | |||
| 180 | attempting to set SIG{__DIE__} yourself, you may interfere with | |||
| 181 | this module's functionality, or this module may interfere with | |||
| 182 | your module's functionality. | |||
| 183 | ||||
| 184 | =head1 MAKING WARNINGS APPEAR AS HTML COMMENTS | |||
| 185 | ||||
| 186 | It is now also possible to make non-fatal errors appear as HTML | |||
| 187 | comments embedded in the output of your program. To enable this | |||
| 188 | feature, export the new "warningsToBrowser" subroutine. Since sending | |||
| 189 | warnings to the browser before the HTTP headers have been sent would | |||
| 190 | cause an error, any warnings are stored in an internal buffer until | |||
| 191 | you call the warningsToBrowser() subroutine with a true argument: | |||
| 192 | ||||
| 193 | use CGI::Carp qw(fatalsToBrowser warningsToBrowser); | |||
| 194 | use CGI qw(:standard); | |||
| 195 | print header(); | |||
| 196 | warningsToBrowser(1); | |||
| 197 | ||||
| 198 | You may also give a false argument to warningsToBrowser() to prevent | |||
| 199 | warnings from being sent to the browser while you are printing some | |||
| 200 | content where HTML comments are not allowed: | |||
| 201 | ||||
| 202 | warningsToBrowser(0); # disable warnings | |||
| 203 | print "<script type=\"text/javascript\"><!--\n"; | |||
| 204 | print_some_javascript_code(); | |||
| 205 | print "//--></script>\n"; | |||
| 206 | warningsToBrowser(1); # re-enable warnings | |||
| 207 | ||||
| 208 | Note: In this respect warningsToBrowser() differs fundamentally from | |||
| 209 | fatalsToBrowser(), which you should never call yourself! | |||
| 210 | ||||
| 211 | =head1 OVERRIDING THE NAME OF THE PROGRAM | |||
| 212 | ||||
| 213 | CGI::Carp includes the name of the program that generated the error or | |||
| 214 | warning in the messages written to the log and the browser window. | |||
| 215 | Sometimes, Perl can get confused about what the actual name of the | |||
| 216 | executed program was. In these cases, you can override the program | |||
| 217 | name that CGI::Carp will use for all messages. | |||
| 218 | ||||
| 219 | The quick way to do that is to tell CGI::Carp the name of the program | |||
| 220 | in its use statement. You can do that by adding | |||
| 221 | "name=cgi_carp_log_name" to your "use" statement. For example: | |||
| 222 | ||||
| 223 | use CGI::Carp qw(name=cgi_carp_log_name); | |||
| 224 | ||||
| 225 | . If you want to change the program name partway through the program, | |||
| 226 | you can use the C<set_progname()> function instead. It is not | |||
| 227 | exported by default, you must import it explicitly by saying | |||
| 228 | ||||
| 229 | use CGI::Carp qw(set_progname); | |||
| 230 | ||||
| 231 | Once you've done that, you can change the logged name of the program | |||
| 232 | at any time by calling | |||
| 233 | ||||
| 234 | set_progname(new_program_name); | |||
| 235 | ||||
| 236 | You can set the program back to the default by calling | |||
| 237 | ||||
| 238 | set_progname(undef); | |||
| 239 | ||||
| 240 | Note that this override doesn't happen until after the program has | |||
| 241 | compiled, so any compile-time errors will still show up with the | |||
| 242 | non-overridden program name | |||
| 243 | ||||
| 244 | =head1 CHANGE LOG | |||
| 245 | ||||
| 246 | 1.29 Patch from Peter Whaite to fix the unfixable problem of CGI::Carp | |||
| 247 | not behaving correctly in an eval() context. | |||
| 248 | ||||
| 249 | 1.05 carpout() added and minor corrections by Marc Hedlund | |||
| 250 | <hedlund@best.com> on 11/26/95. | |||
| 251 | ||||
| 252 | 1.06 fatalsToBrowser() no longer aborts for fatal errors within | |||
| 253 | eval() statements. | |||
| 254 | ||||
| 255 | 1.08 set_message() added and carpout() expanded to allow for FileHandle | |||
| 256 | objects. | |||
| 257 | ||||
| 258 | 1.09 set_message() now allows users to pass a code REFERENCE for | |||
| 259 | really custom error messages. croak and carp are now | |||
| 260 | exported by default. Thanks to Gunther Birznieks for the | |||
| 261 | patches. | |||
| 262 | ||||
| 263 | 1.10 Patch from Chris Dean (ctdean@cogit.com) to allow | |||
| 264 | module to run correctly under mod_perl. | |||
| 265 | ||||
| 266 | 1.11 Changed order of > and < escapes. | |||
| 267 | ||||
| 268 | 1.12 Changed die() on line 217 to CORE::die to avoid B<-w> warning. | |||
| 269 | ||||
| 270 | 1.13 Added cluck() to make the module orthogonal with Carp. | |||
| 271 | More mod_perl related fixes. | |||
| 272 | ||||
| 273 | 1.20 Patch from Ilmari Karonen (perl@itz.pp.sci.fi): Added | |||
| 274 | warningsToBrowser(). Replaced <CODE> tags with <PRE> in | |||
| 275 | fatalsToBrowser() output. | |||
| 276 | ||||
| 277 | 1.23 ineval() now checks both $^S and inspects the message for the "eval" pattern | |||
| 278 | (hack alert!) in order to accommodate various combinations of Perl and | |||
| 279 | mod_perl. | |||
| 280 | ||||
| 281 | 1.24 Patch from Scott Gifford (sgifford@suspectclass.com): Add support | |||
| 282 | for overriding program name. | |||
| 283 | ||||
| 284 | 1.26 Replaced CORE::GLOBAL::die with the evil $SIG{__DIE__} because the | |||
| 285 | former isn't working in some people's hands. There is no such thing | |||
| 286 | as reliable exception handling in Perl. | |||
| 287 | ||||
| 288 | 1.27 Replaced tell STDOUT with bytes=tell STDOUT. | |||
| 289 | ||||
| 290 | =head1 AUTHORS | |||
| 291 | ||||
| 292 | Copyright 1995-2002, Lincoln D. Stein. All rights reserved. | |||
| 293 | ||||
| 294 | This library is free software; you can redistribute it and/or modify | |||
| 295 | it under the same terms as Perl itself. | |||
| 296 | ||||
| 297 | Address bug reports and comments to: lstein@cshl.org | |||
| 298 | ||||
| 299 | =head1 SEE ALSO | |||
| 300 | ||||
| 301 | Carp, CGI::Base, CGI::BasePlus, CGI::Request, CGI::MiniSvr, CGI::Form, | |||
| 302 | CGI::Response | |||
| 303 | if (defined($CGI::Carp::PROGNAME)) | |||
| 304 | { | |||
| 305 | $file = $CGI::Carp::PROGNAME; | |||
| 306 | } | |||
| 307 | ||||
| 308 | =cut | |||
| 309 | ||||
| 310 | require 5.000; | |||
| 311 | use Exporter; | |||
| 312 | #use Carp; | |||
| 313 | BEGIN { | |||
| 314 | require Carp; | |||
| 315 | *CORE::GLOBAL::die = \&CGI::Carp::die; | |||
| 316 | } | |||
| 317 | ||||
| 318 | use File::Spec; | |||
| 319 | ||||
| 320 | @ISA = qw(Exporter); | |||
| 321 | @EXPORT = qw(confess croak carp); | |||
| 322 | @EXPORT_OK = qw(carpout fatalsToBrowser warningsToBrowser wrap set_message set_die_handler set_progname cluck ^name= die); | |||
| 323 | ||||
| 324 | $main::SIG{__WARN__}=\&CGI::Carp::warn; | |||
| 325 | ||||
| 326 | $CGI::Carp::VERSION = '1.29'; | |||
| 327 | $CGI::Carp::CUSTOM_MSG = undef; | |||
| 328 | $CGI::Carp::DIE_HANDLER = undef; | |||
| 329 | ||||
| 330 | ||||
| 331 | # fancy import routine detects and handles 'errorWrap' specially. | |||
| 332 | sub import { | |||
| 333 | my $pkg = shift; | |||
| 334 | my(%routines); | |||
| 335 | my(@name); | |||
| 336 | if (@name=grep(/^name=/,@_)) | |||
| 337 | { | |||
| 338 | my($n) = (split(/=/,$name[0]))[1]; | |||
| 339 | set_progname($n); | |||
| 340 | @_=grep(!/^name=/,@_); | |||
| 341 | } | |||
| 342 | ||||
| 343 | grep($routines{$_}++,@_,@EXPORT); | |||
| 344 | $WRAP++ if $routines{'fatalsToBrowser'} || $routines{'wrap'}; | |||
| 345 | $WARN++ if $routines{'warningsToBrowser'}; | |||
| 346 | my($oldlevel) = $Exporter::ExportLevel; | |||
| 347 | $Exporter::ExportLevel = 1; | |||
| 348 | Exporter::import($pkg,keys %routines); | |||
| 349 | $Exporter::ExportLevel = $oldlevel; | |||
| 350 | $main::SIG{__DIE__} =\&CGI::Carp::die if $routines{'fatalsToBrowser'}; | |||
| 351 | # $pkg->export('CORE::GLOBAL','die'); | |||
| 352 | } | |||
| 353 | ||||
| 354 | # These are the originals | |||
| 355 | 109 | 865µs | 8µs | # spent 1.97ms within CGI::Carp::realwarn which was called 109 times, avg 18µs/call:
# 109 times (1.97ms+0s) by CGI::Carp::warn at line 394, avg 18µs/call |
| 356 | 1 | 10µs | 10µs | # spent 26µs within CGI::Carp::realdie which was called
# once (26µs+0s) by CGI::Carp::die at line 437 |
| 357 | ||||
| 358 | sub id { | |||
| 359 | 110 | 82µs | 745ns | my $level = shift; |
| 360 | 110 | 672µs | 6µs | my($pack,$file,$line,$sub) = caller($level); |
| 361 | 110 | 1.54ms | 14µs | my($dev,$dirs,$id) = File::Spec->splitpath($file); # spent 2.65ms making 110 calls to File::Spec::Unix::splitpath, avg 24µs/call |
| 362 | 110 | 153µs | 1µs | return ($file,$line,$id); |
| 363 | } | |||
| 364 | ||||
| 365 | # spent 10.5ms (8.26+2.26) within CGI::Carp::stamp which was called 109 times, avg 97µs/call:
# 109 times (8.26ms+2.26ms) by CGI::Carp::warn at line 392, avg 97µs/call | |||
| 366 | 109 | 1.22ms | 11µs | my $time = scalar(localtime); |
| 367 | 109 | 40µs | 370ns | my $frame = 0; |
| 368 | 109 | 59µs | 546ns | my ($id,$pack,$file,$dev,$dirs); |
| 369 | 109 | 108µs | 993ns | if (defined($CGI::Carp::PROGNAME)) { |
| 370 | $id = $CGI::Carp::PROGNAME; | |||
| 371 | } else { | |||
| 372 | 109 | 1.48ms | 14µs | do { |
| 373 | 1071 | 267µs | 249ns | $id = $file; |
| 374 | 1071 | 3.34ms | 3µs | ($pack,$file) = caller($frame++); |
| 375 | } until !$file; | |||
| 376 | } | |||
| 377 | 109 | 1.46ms | 13µs | ($dev,$dirs,$id) = File::Spec->splitpath($id); # spent 2.26ms making 109 calls to File::Spec::Unix::splitpath, avg 21µs/call |
| 378 | 109 | 210µs | 2µs | return "[$time] $id: "; |
| 379 | } | |||
| 380 | ||||
| 381 | sub set_progname { | |||
| 382 | $CGI::Carp::PROGNAME = shift; | |||
| 383 | return $CGI::Carp::PROGNAME; | |||
| 384 | } | |||
| 385 | ||||
| 386 | ||||
| 387 | sub warn { | |||
| 388 | 109 | 108µs | 995ns | my $message = shift; |
| 389 | 109 | 1.67ms | 15µs | my($file,$line,$id) = id(1); # spent 5.36ms making 109 calls to CGI::Carp::id, avg 49µs/call |
| 390 | 109 | 316µs | 3µs | $message .= " at $file line $line.\n" unless $message=~/\n$/; |
| 391 | 109 | 49µs | 452ns | _warn($message) if $WARN; |
| 392 | 109 | 1.31ms | 12µs | my $stamp = stamp; # spent 10.5ms making 109 calls to CGI::Carp::stamp, avg 97µs/call |
| 393 | 109 | 417µs | 4µs | $message=~s/^/$stamp/gm; |
| 394 | 109 | 1.27ms | 12µs | realwarn $message; # spent 1.97ms making 109 calls to CGI::Carp::realwarn, avg 18µs/call |
| 395 | } | |||
| 396 | ||||
| 397 | sub _warn { | |||
| 398 | my $msg = shift; | |||
| 399 | if ($EMIT_WARNINGS) { | |||
| 400 | # We need to mangle the message a bit to make it a valid HTML | |||
| 401 | # comment. This is done by substituting similar-looking ISO | |||
| 402 | # 8859-1 characters for <, > and -. This is a hack. | |||
| 403 | $msg =~ tr/<>-/\253\273\255/; | |||
| 404 | chomp $msg; | |||
| 405 | print STDOUT "<!-- warning: $msg -->\n"; | |||
| 406 | } else { | |||
| 407 | push @WARNINGS, $msg; | |||
| 408 | } | |||
| 409 | } | |||
| 410 | ||||
| 411 | ||||
| 412 | # The mod_perl package Apache::Registry loads CGI programs by calling | |||
| 413 | # eval. These evals don't count when looking at the stack backtrace. | |||
| 414 | sub _longmess { | |||
| 415 | my $message = Carp::longmess(); | |||
| 416 | $message =~ s,eval[^\n]+(ModPerl|Apache)/(?:Registry|Dispatch)\w*\.pm.*,,s | |||
| 417 | if exists $ENV{MOD_PERL}; | |||
| 418 | return $message; | |||
| 419 | } | |||
| 420 | ||||
| 421 | # spent 24µs within CGI::Carp::ineval which was called
# once (24µs+0s) by CGI::Carp::die at line 432 | |||
| 422 | 1 | 6µs | 6µs | (exists $ENV{MOD_PERL} ? 0 : $^S) || _longmess() =~ /eval [\{\']/m |
| 423 | } | |||
| 424 | ||||
| 425 | sub die { | |||
| 426 | 1 | 3µs | 3µs | my ($arg,@rest) = @_; |
| 427 | ||||
| 428 | 1 | 500ns | 500ns | if ($DIE_HANDLER) { |
| 429 | &$DIE_HANDLER($arg,@rest); | |||
| 430 | } | |||
| 431 | ||||
| 432 | 1 | 20µs | 20µs | if ( ineval() ) { # spent 24µs making 1 call to CGI::Carp::ineval |
| 433 | 1 | 1µs | 1µs | if (!ref($arg)) { |
| 434 | 1 | 3µs | 3µs | $arg = join("",($arg,@rest)) || "Died"; |
| 435 | 1 | 20µs | 20µs | my($file,$line,$id) = id(1); # spent 81µs making 1 call to CGI::Carp::id |
| 436 | 1 | 6µs | 6µs | $arg .= " at $file line $line.\n" unless $arg=~/\n$/; |
| 437 | 1 | 21µs | 21µs | realdie($arg); # spent 26µs making 1 call to CGI::Carp::realdie |
| 438 | } | |||
| 439 | else { | |||
| 440 | realdie($arg,@rest); | |||
| 441 | } | |||
| 442 | } | |||
| 443 | ||||
| 444 | if (!ref($arg)) { | |||
| 445 | $arg = join("", ($arg,@rest)); | |||
| 446 | my($file,$line,$id) = id(1); | |||
| 447 | $arg .= " at $file line $line." unless $arg=~/\n$/; | |||
| 448 | &fatalsToBrowser($arg) if $WRAP; | |||
| 449 | if (($arg =~ /\n$/) || !exists($ENV{MOD_PERL})) { | |||
| 450 | my $stamp = stamp; | |||
| 451 | $arg=~s/^/$stamp/gm; | |||
| 452 | } | |||
| 453 | if ($arg !~ /\n$/) { | |||
| 454 | $arg .= "\n"; | |||
| 455 | } | |||
| 456 | } | |||
| 457 | realdie $arg; | |||
| 458 | } | |||
| 459 | ||||
| 460 | sub set_message { | |||
| 461 | $CGI::Carp::CUSTOM_MSG = shift; | |||
| 462 | return $CGI::Carp::CUSTOM_MSG; | |||
| 463 | } | |||
| 464 | ||||
| 465 | sub set_die_handler { | |||
| 466 | ||||
| 467 | my ($handler) = shift; | |||
| 468 | ||||
| 469 | #setting SIG{__DIE__} here is necessary to catch runtime | |||
| 470 | #errors which are not called by literally saying "die", | |||
| 471 | #such as the line "undef->explode();". however, doing this | |||
| 472 | #will interfere with fatalsToBrowser, which also sets | |||
| 473 | #SIG{__DIE__} in the import() function above (or the | |||
| 474 | #import() function above may interfere with this). for | |||
| 475 | #this reason, you should choose to either set the die | |||
| 476 | #handler here, or use fatalsToBrowser, not both. | |||
| 477 | $main::SIG{__DIE__} = $handler; | |||
| 478 | ||||
| 479 | $CGI::Carp::DIE_HANDLER = $handler; | |||
| 480 | ||||
| 481 | return $CGI::Carp::DIE_HANDLER; | |||
| 482 | } | |||
| 483 | ||||
| 484 | sub confess { CGI::Carp::die Carp::longmess @_; } | |||
| 485 | sub croak { CGI::Carp::die Carp::shortmess @_; } | |||
| 486 | sub carp { CGI::Carp::warn Carp::shortmess @_; } | |||
| 487 | sub cluck { CGI::Carp::warn Carp::longmess @_; } | |||
| 488 | ||||
| 489 | # We have to be ready to accept a filehandle as a reference | |||
| 490 | # or a string. | |||
| 491 | sub carpout { | |||
| 492 | my($in) = @_; | |||
| 493 | my($no) = fileno(to_filehandle($in)); | |||
| 494 | realdie("Invalid filehandle $in\n") unless defined $no; | |||
| 495 | ||||
| 496 | open(SAVEERR, ">&STDERR"); | |||
| 497 | open(STDERR, ">&$no") or | |||
| 498 | ( print SAVEERR "Unable to redirect STDERR: $!\n" and exit(1) ); | |||
| 499 | } | |||
| 500 | ||||
| 501 | sub warningsToBrowser { | |||
| 502 | $EMIT_WARNINGS = @_ ? shift : 1; | |||
| 503 | _warn(shift @WARNINGS) while $EMIT_WARNINGS and @WARNINGS; | |||
| 504 | } | |||
| 505 | ||||
| 506 | # headers | |||
| 507 | sub fatalsToBrowser { | |||
| 508 | my($msg) = @_; | |||
| 509 | $msg=~s/&/&/g; | |||
| 510 | $msg=~s/>/>/g; | |||
| 511 | $msg=~s/</</g; | |||
| 512 | $msg=~s/\"/"/g; | |||
| 513 | my($wm) = $ENV{SERVER_ADMIN} ? | |||
| 514 | qq[the webmaster (<a href="mailto:$ENV{SERVER_ADMIN}">$ENV{SERVER_ADMIN}</a>)] : | |||
| 515 | "this site's webmaster"; | |||
| 516 | my ($outer_message) = <<END; | |||
| 517 | For help, please send mail to $wm, giving this error message | |||
| 518 | and the time and date of the error. | |||
| 519 | END | |||
| 520 | ; | |||
| 521 | my $mod_perl = exists $ENV{MOD_PERL}; | |||
| 522 | ||||
| 523 | if ($CUSTOM_MSG) { | |||
| 524 | if (ref($CUSTOM_MSG) eq 'CODE') { | |||
| 525 | print STDOUT "Content-type: text/html\n\n" | |||
| 526 | unless $mod_perl; | |||
| 527 | &$CUSTOM_MSG($msg); # nicer to perl 5.003 users | |||
| 528 | return; | |||
| 529 | } else { | |||
| 530 | $outer_message = $CUSTOM_MSG; | |||
| 531 | } | |||
| 532 | } | |||
| 533 | ||||
| 534 | my $mess = <<END; | |||
| 535 | <h1>Software error:</h1> | |||
| 536 | <pre>$msg</pre> | |||
| 537 | <p> | |||
| 538 | $outer_message | |||
| 539 | </p> | |||
| 540 | END | |||
| 541 | ; | |||
| 542 | ||||
| 543 | if ($mod_perl) { | |||
| 544 | my $r; | |||
| 545 | if ($ENV{MOD_PERL_API_VERSION} && $ENV{MOD_PERL_API_VERSION} == 2) { | |||
| 546 | $mod_perl = 2; | |||
| 547 | require Apache2::RequestRec; | |||
| 548 | require Apache2::RequestIO; | |||
| 549 | require Apache2::RequestUtil; | |||
| 550 | require APR::Pool; | |||
| 551 | require ModPerl::Util; | |||
| 552 | require Apache2::Response; | |||
| 553 | $r = Apache2::RequestUtil->request; | |||
| 554 | } | |||
| 555 | else { | |||
| 556 | $r = Apache->request; | |||
| 557 | } | |||
| 558 | # If bytes have already been sent, then | |||
| 559 | # we print the message out directly. | |||
| 560 | # Otherwise we make a custom error | |||
| 561 | # handler to produce the doc for us. | |||
| 562 | if ($r->bytes_sent) { | |||
| 563 | $r->print($mess); | |||
| 564 | $mod_perl == 2 ? ModPerl::Util::exit(0) : $r->exit; | |||
| 565 | } else { | |||
| 566 | # MSIE won't display a custom 500 response unless it is >512 bytes! | |||
| 567 | if ($ENV{HTTP_USER_AGENT} =~ /MSIE/) { | |||
| 568 | $mess = "<!-- " . (' ' x 513) . " -->\n$mess"; | |||
| 569 | } | |||
| 570 | $r->custom_response(500,$mess); | |||
| 571 | } | |||
| 572 | } else { | |||
| 573 | my $bytes_written = eval{tell STDOUT}; | |||
| 574 | if (defined $bytes_written && $bytes_written > 0) { | |||
| 575 | print STDOUT $mess; | |||
| 576 | } | |||
| 577 | else { | |||
| 578 | print STDOUT "Content-type: text/html\n\n"; | |||
| 579 | print STDOUT $mess; | |||
| 580 | } | |||
| 581 | } | |||
| 582 | ||||
| 583 | warningsToBrowser(1); # emit warnings before dying | |||
| 584 | } | |||
| 585 | ||||
| 586 | # Cut and paste from CGI.pm so that we don't have the overhead of | |||
| 587 | # always loading the entire CGI module. | |||
| 588 | sub to_filehandle { | |||
| 589 | my $thingy = shift; | |||
| 590 | return undef unless $thingy; | |||
| 591 | return $thingy if UNIVERSAL::isa($thingy,'GLOB'); | |||
| 592 | return $thingy if UNIVERSAL::isa($thingy,'FileHandle'); | |||
| 593 | if (!ref($thingy)) { | |||
| 594 | my $caller = 1; | |||
| 595 | while (my $package = caller($caller++)) { | |||
| 596 | my($tmp) = $thingy=~/[\':]/ ? $thingy : "$package\:\:$thingy"; | |||
| 597 | return $tmp if defined(fileno($tmp)); | |||
| 598 | } | |||
| 599 | } | |||
| 600 | return undef; | |||
| 601 | } | |||
| 602 | ||||
| 603 | 1; |