File Coverage

blib/lib/cPanel/TaskQueue/ChildProcessor.pm
Criterion Covered Total %
statement 32 50 64.0
branch 5 12 41.6
condition 5 9 55.5
subroutine 7 10 70.0
pod 4 4 100.0
total 53 85 62.3


line stmt bran cond sub pod time code
1             package cPanel::TaskQueue::ChildProcessor;
2             {
3             $cPanel::TaskQueue::ChildProcessor::VERSION = '0.606';
4             }
5              
6             # cpanel - cPanel/TaskQueue/ChildProcessor.pm Copyright(c) 2014 cPanel, Inc.
7             # All rights Reserved.
8             # copyright@cpanel.net http://cpanel.net
9             #
10             # Redistribution and use in source and binary forms, with or without
11             # modification, are permitted provided that the following conditions are met:
12             # * Redistributions of source code must retain the above copyright
13             # notice, this list of conditions and the following disclaimer.
14             # * Redistributions in binary form must reproduce the above copyright
15             # notice, this list of conditions and the following disclaimer in the
16             # documentation and/or other materials provided with the distribution.
17             # * Neither the name of the owner nor the names of its contributors may
18             # be used to endorse or promote products derived from this software
19             # without specific prior written permission.
20             #
21             # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22             # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23             # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24             # DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY
25             # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26             # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27             # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28             # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29             # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30             # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31              
32 11     11   37046 use strict;
  11         24  
  11         414  
33              
34             #use warnings;
35 11     11   54 use base 'cPanel::TaskQueue::Processor';
  11         14  
  11         1388  
36 11     11   7142 use cPanel::TaskQueue::Scheduler ();
  11         31  
  11         5469  
37              
38             {
39              
40             sub get_child_timeout {
41 6     6 1 701 my ($self) = @_;
42 6         1002 return;
43             }
44              
45             sub get_reschedule_delay {
46 3     3 1 5 my ( $self, $task ) = @_;
47              
48 3         13 return 15 * 60;
49             }
50              
51             sub retry_task {
52 3     3 1 7 my ( $self, $task, $delay ) = @_;
53 3   66     14 $delay ||= $self->get_reschedule_delay($task);
54              
55 3         11 $task->decrement_retries();
56 3 50 66     26 if ( $task->retries_remaining() and $task->get_userdata('sched') ) {
57 0         0 my $s = cPanel::TaskQueue::Scheduler->new( { token => $task->get_userdata('sched') } );
58              
59             # This will either succeed or exception.
60 0         0 $s->schedule_task( $task, { delay_seconds => $delay } );
61             }
62              
63 3         33 return;
64             }
65              
66             sub process_task {
67 20     20 1 40 my ( $self, $task, $logger ) = @_;
68 20         25092 my $pid = fork();
69              
70 20 50       1614 $logger->throw( q{Unable to start a child process to handle the '} . $task->command() . "' task\n" )
71             unless defined $pid;
72              
73             # Parent returns
74 20 100       1656 return $pid if $pid;
75              
76 5   33     2010 my $timeout = $self->get_child_timeout() || $task->child_timeout();
77 5         43 my $oldalarm;
78             eval {
79 5         589 local $SIG{'CHLD'} = 'DEFAULT';
80 5     0   425 local $SIG{'ALRM'} = sub { die "timeout detected\n"; };
  0         0  
81 5         117 $oldalarm = alarm $timeout;
82 5         113 $self->_do_child_task( $task, $logger );
83 5         1252699 alarm $oldalarm;
84 5         317 1;
85 5 50       102 } or do {
86 0         0 my $ex = $@;
87 0         0 alarm $oldalarm;
88 0 0       0 if ( $ex eq "timeout detected\n" ) {
89 0         0 eval {
90              
91             # TODO: consider adding another timeout in case this handling
92             # locks up.
93 0         0 $self->_do_timeout($task);
94              
95             # Handle retries
96 0         0 $self->retry_task($task);
97             };
98              
99             # Don't throw, we want to exit instead.
100 0 0       0 if ($@) {
101 0         0 $logger->warn($@);
102 0         0 exit 1;
103             }
104             }
105             else {
106              
107             # Don't throw, we want to exit instead.
108 0         0 $logger->warn($ex);
109 0         0 exit 1;
110             }
111             };
112 5         478 exit 0;
113             }
114              
115             sub _do_timeout {
116 0     0     my ( $self, $task ) = @_;
117              
118 0           return;
119             }
120              
121             sub _do_child_task {
122 0     0     my ( $self, $task, $logger ) = @_;
123              
124 0           $logger->throw("No child task defined.\n");
125             }
126             }
127              
128             1;
129              
130             __END__