Race between cron and crontab
John Baldwin
jhb at freebsd.org
Tue Jan 31 16:49:34 UTC 2012
A co-worker ran into a race between updating a cron tab via crontab(8) and
cron(8) yesterday. Specifically, cron(8) failed to notice that a crontab was
updated. The problem is that 1) by default our filesystems only use second
granularity for timestamps and 2) cron only caches the seconds portion of a
file's timestamp when checking for changes anyway. This means that cron can
miss updates to a spool directory if multiple updates to the directory are
performed within a single second and cron wakes up to scan the spool directory
within the same second and scans it before all of the updates are complete.
Specifically, when replacing a crontab, crontab(8) first creates a temporary
file in /var/cron/tabs and then uses a rename to install it followed by
touching the spool directory to update its modification time. However, the
creation of the temporary file already changes the modification time of the
directory, and cron may "miss" the rename if it scans the directory in between
the creation of the temporary file and the rename.
The "fix" I am planning to use locally is to simply force crontab(8) to sleep
for a second before it touches the spool directory, thus ensuring that it the
touch of the spool directory will use a later modification time than the
creation of the temporary file.
Note that crontab -r is not affected by this race as it only does one atomic
update to the directory (unlink()).
Index: crontab.c
===================================================================
--- crontab.c (revision 225431)
+++ crontab.c (working copy)
@@ -604,6 +604,15 @@ replace_cmd() {
log_it(RealUser, Pid, "REPLACE", User);
+ /*
+ * Creating the 'tn' temp file has already updated the
+ * modification time of the spool directory. Sleep for a
+ * second to ensure that poke_daemon() sets a later
+ * modification time. Otherwise, this can race with the cron
+ * daemon scanning for updated crontabs.
+ */
+ sleep(1);
+
poke_daemon();
return (0);
--
John Baldwin
More information about the freebsd-current
mailing list