summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-02-22 16:17:11 +0200
committerSergey Poznyakoff <gray@gnu.org>2018-02-22 16:17:11 +0200
commita69997afd7c96a6f6c91a6a88653c37387b09190 (patch)
tree11802f0584b088729127814ff561993109f0b86b
parentc16f2363476167d59a2eaad38ef9e98f032ebdd1 (diff)
downloadapache-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.pm103
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
14sub new { 14sub 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
95sub _get_version_info { 121sub _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
136my @ATTRIBUTES = qw(name 159my @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
159sub defines { 179sub 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
291sub preloaded { 310sub 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
300sub _get_module_info { 318sub _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
3151; 3301;
@@ -371,12 +386,38 @@ in file F</etc/apache2/envvars>. This attribute is intended to cope with
371such problems, e.g.: 386such 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
392Controls the error handling. Allowed values are C<croak> and C<return>.
393If the value is C<croak> (the default), the method will I<croak> if an
394error occurs. If set to C<return>, the constructor will return a valid
395object. The B<httpd> exit status and diagnostics emitted to the stderr
396will be available via the B<status> and B<error> methods.
397
375=back 398=back
376 399
377The method will I<croak> if an error occurs (e.g. the server binary 400The method will I<croak> if an error occurs (e.g. the server binary
378is not found or exits with failure). 401is 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
410Returns the status of the last B<httpd> invocation (i.e. the value of
411the B<$?> perl variable after B<waitpid>). The caller should inspect
412this value, after constructing an B<Apache::Defaults> object with
413the C<on_error> attribute set to C<return>.
414
415=head2 error
416
417Returns additional diagnostics if B<$x-E<gt>status != 0>. Normally, these are
418diagnostic messages that B<httpd> printed to standard error before
419termination.