# Used for getting lock in the database my $lockname = $class.'::'.$handler; # Get exclusive lock on jobs table # clear_cache deletes the cached db handles in DBI # so that the next connect should get a fresh handle MyStuff::DB::clear_cache(); my $db = MyStuff::DB->connect('default'); my $lock = $db->dbh; $lock->do('LOCK TABLES jobs WRITE'); # Get existing info for job status $db = $db->select_row({ bind => ['CHAR'], params => [$lockname], SQL => 'SELECT pid,last_id,last_run||"1970-01-01" FROM jobs WHERE name = ?' }); my $results = $db->results; # If job is still running if ($results && $results->{pid} && kill 0 => $results->{pid}) { logmsg("Still running"); $lock->do('UNLOCK TABLES'); $Starts{$lockname}++; if ($Starts{$lockname}>5) { warn "Tried to start $class => $handler $Starts{$lockname} times"; } return; } # Start new job logmsg ("Starting '$lockname'"); my $current_time = timestamp(); # Last time the job was run # the last ID processed, or the last # time it was run was.... my $last_run = $results->{last_run} ? $results->{last_run}->strftime('%F %T') : '1970-01-01'; my $last = { id => $results->{last_id}||0, run => $last_run, time => $current_time, }; # Fork you my $pid = fork; unless (defined $pid) { warn "Couldn't fork to start $class => $handler : $!"; return; } if ($pid) { # Parent # Update jobs table with new PID # THIS IS THE POINT AT WHICH IT HANGS # AND IN THE DB LOGS, IT HAS THE SAME CONNECTION # ID AS THE HANDLE WHICH OBTAINED THE LOCK $db = $db->replace({ bind => ['CHAR','INT','INT','DATE'], params => [$lockname, $pid, $last->{id}, $last->{run}], SQL => <do('UNLOCK TABLES'); $Starts{$lockname}=0; return; } # Child # Get rid of old database connections MyStuff::DB::clear_cache(); chdir '/' or die $!; open STDIN, '/dev/null' or die $!; # Checking that my job has had my PID set for me $db = MyStuff::DB->connect('default.write'); $db->select_row({ bind => ['CHAR'], params => [$lockname], SQL => <results; unless ($results && $results->{pid} == $$) { die "Jobs table not locked for me" } # Run handler eval {$class->$handler($last,$args)}; if ($@) { die "Error running '$lockname' : $@"; } # Reset jobs table $db = MyStuff::DB->update({ db => 'default.write', bind => ['INT','DATE','CHAR','INT'], params => [$last->{id}, $last->{time}, $lockname, $$], SQL => <