I'm trying to write a daemon to emulate the cron scheduler for a collection of miscellaneous Perl scripts lying around our servers. Essentially, crontab entries will be stored in a database table and this daemon should poll the db every so often to refresh my psuedo crontab file. Once a minute, it will determine which scripts to run, and fork off a new process to exec() it.
There are two reasons we're not using cron here. First is that we don't want to allow people to edit crontabs willy-nilly as they create custom scripts they want run periodically. And secondly, as far as I know, cron doesn't have any sort of logging feature. We need to track what scripts ran, what kind of exit codes they produced when (if) they completed, etc. in the case of database or server outages. It'll make our lives a WHOLE lot easier if we could track down what needed to be rerun and why. Right now, no such mechanism is in place and system downtime is a disaster.
Finally, my question. This daemon wakes up once a minute and forks off processes as necessary. The problem are the incoming SIGCHLD signals the daemon receives during this time and, more critically, while its sleeping off the remainder of the minute before the next iteration. If I set $SIG{CHLD} to 'IGNORE' I don't have to worry about reaping the children as they die, but I also can't track exit statuses. However, if I set up any kind of handler, it can interrupt the process as it sleeps or at any other time, even with safe signals in 5.8.7.
So, is there a clean way to avoid this problem? Ideally, I'd like a system that can avoid defunct processes sitting around in the process table at all, but that's livable provided they're reaped and their exit statuses returned to me in a timely fashion.
There are two approaches that I've thought of, but can't seem to implement either. Any advice would be helpful:
-or-
2) Call a reaper function at the beginning of each minute's iteration to clean up any processes that have completed since the last harvest. Is there a way to defer any CHLD signals until after the daemon has forked off any necessary children and slept? This is the only way I could foresee this particular approach being successful, though again I'm open to suggestion. I've tried using sigprocmask, but it seems finicky at best as the signals I know have been generated are skipped for at least one additional iteration before they're received.
Clearly option 1 is the cleanest approach, but is it possible to accomplish?
In reply to SIGCHLD and sleep() by overbyte
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |