diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-02-22 16:17:11 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-02-22 16:17:11 +0200 |
commit | a69997afd7c96a6f6c91a6a88653c37387b09190 (patch) | |
tree | 11802f0584b088729127814ff561993109f0b86b | |
parent | c16f2363476167d59a2eaad38ef9e98f032ebdd1 (diff) | |
download | apache-defaults-a69997afd7c96a6f6c91a6a88653c37387b09190.tar.gz apache-defaults-a69997afd7c96a6f6c91a6a88653c37387b09190.tar.bz2 |
Provide alternative error handling
New constructor parameter on_error controls error handling.
-rw-r--r-- | lib/Apache/Defaults.pm | 103 |
1 files changed, 72 insertions, 31 deletions
diff --git a/lib/Apache/Defaults.pm b/lib/Apache/Defaults.pm index 08c4865..b980333 100644 --- a/lib/Apache/Defaults.pm +++ b/lib/Apache/Defaults.pm | |||
@@ -13,9 +13,16 @@ our $VERSION = '0.10'; | |||
13 | 13 | ||
14 | sub new { | 14 | sub new { |
15 | my $class = shift; | 15 | my $class = shift; |
16 | my $self = bless {}, $class; | 16 | my $self = bless { on_error => 'croak' }, $class; |
17 | local %_ = @_; | 17 | local %_ = @_; |
18 | my $v; | 18 | my $v; |
19 | |||
20 | if (my $v = delete $_{on_error}) { | ||
21 | croak "invalid on_error value" | ||
22 | unless grep { $_ eq $v } qw(croak return); | ||
23 | $self->{on_error} = $v; | ||
24 | } | ||
25 | |||
19 | my @servlist; | 26 | my @servlist; |
20 | if ($v = delete $_{server}) { | 27 | if ($v = delete $_{server}) { |
21 | if (ref($v) eq 'ARRAY') { | 28 | if (ref($v) eq 'ARRAY') { |
@@ -30,6 +37,9 @@ sub new { | |||
30 | if (my @select = grep { -x $_->[0] } | 37 | if (my @select = grep { -x $_->[0] } |
31 | map { [ shellwords($_) ] } @servlist) { | 38 | map { [ shellwords($_) ] } @servlist) { |
32 | $self->{server} = shift @select; | 39 | $self->{server} = shift @select; |
40 | } elsif ($self->{on_error} eq 'return') { | ||
41 | $self->{status} = 127; | ||
42 | $self->{error} = "No suitable httpd binary found"; | ||
33 | } else { | 43 | } else { |
34 | croak "No suitable httpd binary found"; | 44 | croak "No suitable httpd binary found"; |
35 | } | 45 | } |
@@ -38,12 +48,22 @@ sub new { | |||
38 | my $env = Shell::GetEnv->new('sh', ". $v", | 48 | my $env = Shell::GetEnv->new('sh', ". $v", |
39 | { startup => 0 }); | 49 | { startup => 0 }); |
40 | if ($env->status) { | 50 | if ($env->status) { |
41 | croak "Got status ".$env->status." trying to inherit environment"; | 51 | if ($self->{on_error} eq 'return') { |
52 | $self->{status} = $env->status; | ||
53 | $self->{error} = "Failed to inherit environment"; | ||
54 | } else { | ||
55 | croak sprintf("Got status %d trying to inherit environment", | ||
56 | $env->status); | ||
57 | } | ||
42 | } | 58 | } |
43 | $self->{environ} = $env->envs; | 59 | $self->{environ} = $env->envs; |
44 | } | 60 | } |
45 | 61 | ||
46 | croak "unrecognized arguments" if keys(%_); | 62 | croak "unrecognized arguments" if keys(%_); |
63 | |||
64 | $self->_get_version_info unless $self->status; | ||
65 | $self->_get_module_info unless $self->status; | ||
66 | |||
47 | return $self; | 67 | return $self; |
48 | } | 68 | } |
49 | 69 | ||
@@ -67,16 +87,22 @@ sub probe { | |||
67 | last unless &{$cb}($_); | 87 | last unless &{$cb}($_); |
68 | } | 88 | } |
69 | waitpid($pid, 0); | 89 | waitpid($pid, 0); |
70 | if ($? == -1) { | 90 | if ($self->{on_error} eq 'croak') { |
71 | croak "failed to execute " .$self->server . ": $!"; | 91 | if ($? == -1) { |
72 | } elsif ($? & 127) { | 92 | croak "failed to execute " .$self->server . ": $!"; |
73 | croak sprintf("%s died with signal %d%s", | 93 | } elsif ($? & 127) { |
74 | $self->server, $? & 127, | 94 | croak sprintf("%s died with signal %d%s", |
75 | ($? & 128) ? ' (core dumped)' : ''); | 95 | $self->server, $? & 127, |
76 | } elsif (my $code = $? >> 8) { | 96 | ($? & 128) ? ' (core dumped)' : ''); |
77 | local $/ = undef; | 97 | } elsif (my $code = $? >> 8) { |
78 | croak sprintf("%s terminated with status %d; error message: %s", | 98 | local $/ = undef; |
79 | $self->server, $code, <$err>); | 99 | croak sprintf("%s terminated with status %d; error message: %s", |
100 | $self->server, $code, <$err>); | ||
101 | } | ||
102 | } elsif ($?) { | ||
103 | local $/ = undef; | ||
104 | $self->{status} = $?; | ||
105 | $self->{error} = <$err>; | ||
80 | } | 106 | } |
81 | } | 107 | } |
82 | close $nullin; | 108 | close $nullin; |
@@ -94,8 +120,7 @@ sub dequote { | |||
94 | 120 | ||
95 | sub _get_version_info { | 121 | sub _get_version_info { |
96 | my $self = shift; | 122 | my $self = shift; |
97 | unless ($self->{has_version_info}) { | 123 | $self->probe(sub { |
98 | $self->probe(sub { | ||
99 | local $_ = shift; | 124 | local $_ = shift; |
100 | if (m{^Server version:\s+(.+?)/(\S+)\s+\((.*?)\)}) { | 125 | if (m{^Server version:\s+(.+?)/(\S+)\s+\((.*?)\)}) { |
101 | $self->{name} = $1; | 126 | $self->{name} = $1; |
@@ -129,11 +154,10 @@ sub _get_version_info { | |||
129 | } | 154 | } |
130 | return 1; | 155 | return 1; |
131 | }, '-V'); | 156 | }, '-V'); |
132 | } | ||
133 | $self->{has_version_info} = 1; | ||
134 | } | 157 | } |
135 | 158 | ||
136 | my @ATTRIBUTES = qw(name | 159 | my @ATTRIBUTES = qw(status error |
160 | name | ||
137 | version | 161 | version |
138 | platform | 162 | platform |
139 | built | 163 | built |
@@ -146,11 +170,7 @@ my @ATTRIBUTES = qw(name | |||
146 | { | 170 | { |
147 | no strict 'refs'; | 171 | no strict 'refs'; |
148 | foreach my $attribute (@ATTRIBUTES) { | 172 | foreach my $attribute (@ATTRIBUTES) { |
149 | *{ __PACKAGE__ . '::' . $attribute } = sub { | 173 | *{ __PACKAGE__ . '::' . $attribute } = sub { shift->{$attribute} } |
150 | my $self = shift; | ||
151 | $self->_get_version_info; | ||
152 | $self->{$attribute}; | ||
153 | } | ||
154 | } | 174 | } |
155 | } | 175 | } |
156 | 176 | ||
@@ -158,7 +178,6 @@ sub server_root { shift->defines('HTTPD_ROOT') } | |||
158 | 178 | ||
159 | sub defines { | 179 | sub defines { |
160 | my $self = shift; | 180 | my $self = shift; |
161 | $self->_get_version_info; | ||
162 | if (@_) { | 181 | if (@_) { |
163 | return @{$self->{defines}}{@_}; | 182 | return @{$self->{defines}}{@_}; |
164 | } | 183 | } |
@@ -290,7 +309,6 @@ my %modlist = ( | |||
290 | 309 | ||
291 | sub preloaded { | 310 | sub preloaded { |
292 | my $self = shift; | 311 | my $self = shift; |
293 | $self->_get_module_info; | ||
294 | if (@_) { | 312 | if (@_) { |
295 | return @{$self->{preloaded}}{@_}; | 313 | return @{$self->{preloaded}}{@_}; |
296 | } | 314 | } |
@@ -299,8 +317,7 @@ sub preloaded { | |||
299 | 317 | ||
300 | sub _get_module_info { | 318 | sub _get_module_info { |
301 | my $self = shift; | 319 | my $self = shift; |
302 | unless ($self->{has_module_info}) { | 320 | $self->probe(sub { |
303 | $self->probe(sub { | ||
304 | local $_ = shift; | 321 | local $_ = shift; |
305 | # print "GOT $_\n"; | 322 | # print "GOT $_\n"; |
306 | if (/^\s*(\S+\.c)$/ && exists($modlist{$1})) { | 323 | if (/^\s*(\S+\.c)$/ && exists($modlist{$1})) { |
@@ -308,8 +325,6 @@ sub _get_module_info { | |||
308 | } | 325 | } |
309 | return 1; | 326 | return 1; |
310 | }, '-l'); | 327 | }, '-l'); |
311 | $self->{has_module_info} = 1; | ||
312 | } | ||
313 | } | 328 | } |
314 | 329 | ||
315 | 1; | 330 | 1; |
@@ -371,12 +386,38 @@ in file F</etc/apache2/envvars>. This attribute is intended to cope with | |||
371 | such problems, e.g.: | 386 | such problems, e.g.: |
372 | 387 | ||
373 | $x = new Apache::Defaults(environ => /etc/apache2/envvars) | 388 | $x = new Apache::Defaults(environ => /etc/apache2/envvars) |
374 | 389 | ||
390 | =item C<on_error> | ||
391 | |||
392 | Controls the error handling. Allowed values are C<croak> and C<return>. | ||
393 | If the value is C<croak> (the default), the method will I<croak> if an | ||
394 | error occurs. If set to C<return>, the constructor will return a valid | ||
395 | object. The B<httpd> exit status and diagnostics emitted to the stderr | ||
396 | will be available via the B<status> and B<error> methods. | ||
397 | |||
375 | =back | 398 | =back |
376 | 399 | ||
377 | The method will I<croak> if an error occurs (e.g. the server binary | 400 | The method will I<croak> if an error occurs (e.g. the server binary |
378 | is not found or exits with failure). | 401 | is not found or exits with failure). |
379 | 402 | ||
403 | =head2 status | ||
404 | |||
405 | $x = new Apache::Defaults(on_error => 'return'); | ||
406 | if ($x->status) { | ||
407 | die $x->error; | ||
408 | } | ||
409 | |||
410 | Returns the status of the last B<httpd> invocation (i.e. the value of | ||
411 | the B<$?> perl variable after B<waitpid>). The caller should inspect | ||
412 | this value, after constructing an B<Apache::Defaults> object with | ||
413 | the C<on_error> attribute set to C<return>. | ||
414 | |||
415 | =head2 error | ||
416 | |||
417 | Returns additional diagnostics if B<$x-E<gt>status != 0>. Normally, these are | ||
418 | diagnostic messages that B<httpd> printed to standard error before | ||
419 | termination. | ||