http://qs1969.pair.com?node_id=737658


in reply to Re: A perl daemon
in thread A perl daemon

However, I found that the dispatcher function within the class is a new process every time it executes. So if I update the cron, the changes are lost once the function completes.

You mean, if you were to update the cron table from one of the jobs? Yes, those changes would be lost.

I've been using the example code above in production for 2 years now, and it runs beautifully. I have a large application, which gets loaded at startup, and using fork to launch each process on linux is really cheap (as it makes use of Copy on Write). It also means that different jobs can run simultaneously.

In Schedule::Cron there is an option nofork, which (not surprisingly) launches the jobs without forking :) - this would let you alter your cron table, but would only run jobs sequentially.

Instead of that, you could consider making your daemon re-read the cron table whenever it receives a signal of your choosing, eg $SIG{USR}, then your child job could update the cron table, and signal its parent.

Replies are listed 'Best First'.
Re : A perl daemon
by trm (Novice) on Jan 20, 2009 at 21:02 UTC
    Thank you for your response.

    I just need "something" to update the cron. I was thinking that I could get the parent to update the cron in a while loop, but it looks like after I "run" the schedule, the schedule seems to have control - i.e. until it completes, the next lines in what you called "init_cron_daemon" won't execute.

    Perhaps I just need the schedule to signal the parent to update the cron. I just need to research how I signal that parent.

    The only thing preventing me from using this is updating the cron on the fly. I found that deleting crons caused table problems, but I wrote workarounds for that. Now I need to avoid the forking - or precisely as you state, work around it somehow.

      For handling signals, have a look at perlipc, especially the section entitled Handling the SIGHUP Signal in Daemons.

      You probably want something like this (untested):

      sub reload_cron { my $cron = shift; my $file = shift; $cron->clean_timetable; $cron->load_crontab($file); } { local $SIG{USR1} = sub { reload_cron($cron,$file) }; $cron->run; }
      Then to signal the cron daemon, you need it's PID, and you can do:
      kill $pid,10; # SIGUSR1

      Hope this helps>

        Thank you again for the information. I'll take a look at the module. I think the explanation is a bit beyond my grasp, but hopefully with the module docs that will clear up my confusion.

        I did try the nofork alternative, which I thought would be appropriate as I am using a governed queue with my application, and a fork could potentially effect it. However, it seems that if I have multiple schedules at the same time, only one schedule (somewhat random choice) will execute. I imagined that one would execute, then the next would execute, followed by however many are waiting to process. Any experience with the nofork mode that you might shed some light on?