summaryrefslogtreecommitdiffstats
path: root/Bugzilla/JobQueue.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/JobQueue.pm')
-rw-r--r--Bugzilla/JobQueue.pm60
1 files changed, 60 insertions, 0 deletions
diff --git a/Bugzilla/JobQueue.pm b/Bugzilla/JobQueue.pm
index 7ea678345..053928dd0 100644
--- a/Bugzilla/JobQueue.pm
+++ b/Bugzilla/JobQueue.pm
@@ -27,7 +27,9 @@ use strict;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Install::Util qw(install_string);
+use File::Slurp;
use base qw(TheSchwartz);
+use fields qw(_worker_pidfile);
# This maps job names for Bugzilla::JobQueue to the appropriate modules.
# If you add new types of jobs, you should add a mapping here.
@@ -99,6 +101,64 @@ sub insert {
return $retval;
}
+# To avoid memory leaks/fragmentation which tends to happen for long running
+# perl processes; check for jobs, and spawn a new process to empty the queue.
+sub subprocess_worker {
+ my $self = shift;
+
+ my $command = "$0 -p '" . $self->{_worker_pidfile} . "' onepass";
+
+ while (1) {
+ my $time = (time);
+ my @jobs = $self->list_jobs({
+ funcname => $self->{all_abilities},
+ run_after => $time,
+ grabbed_until => $time,
+ limit => 1,
+ });
+ if (@jobs) {
+ $self->debug("Spawning queue worker process");
+ # Run the worker as a daemon
+ system $command;
+ # And poll the PID to detect when the working has finished.
+ # We do this instead of system() to allow for the INT signal to
+ # interrup us and trigger kill_worker().
+ my $pid = read_file($self->{_worker_pidfile}, err_mode => 'quiet');
+ if ($pid) {
+ sleep(3) while(kill(0, $pid));
+ }
+ $self->debug("Queue worker process completed");
+ } else {
+ $self->debug("No jobs found");
+ }
+ sleep(5);
+ }
+}
+
+sub kill_worker {
+ my $self = Bugzilla->job_queue();
+ if ($self->{_worker_pidfile} && -e $self->{_worker_pidfile}) {
+ my $worker_pid = read_file($self->{_worker_pidfile});
+ if ($worker_pid && kill(0, $worker_pid)) {
+ $self->debug("Stopping worker process");
+ system "$0 -f -p '" . $self->{_worker_pidfile} . "' stop";
+ }
+ }
+}
+
+sub set_pidfile {
+ my ($self, $pidfile) = @_;
+ $pidfile =~ s/^(.+)(\..+)$/$1.worker$2/;
+ $self->{_worker_pidfile} = $pidfile;
+}
+
+# Clear the request cache at the start of each run.
+sub work_once {
+ my $self = shift;
+ Bugzilla->clear_request_cache();
+ return $self->SUPER::work_once(@_);
+}
+
1;
__END__