Re: Race between cron and crontab

From: Ian Lepore <freebsd_at_damnhippie.dyndns.org>
Date: Thu, 02 Feb 2012 18:44:59 -0700
On Thu, 2012-02-02 at 17:03 -0800, Doug Barton wrote:
> On 02/01/2012 04:42, John Baldwin wrote:
> > On Tuesday, January 31, 2012 9:23:12 pm Doug Barton wrote:
> >> On 01/31/2012 08:49, John Baldwin wrote:
> >>> 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.
> >>
> >> If you really want cron to have sub-second granularity I don't see how
> >> you could do it without using flags.
> >>
> >> crontab open	sets flag that it is editing a file
> >> crontab close	clears "editing" flag, sets "something changed" flag
> >> 		(if something actually changed of course)
> >>
> >> cron	checks existence of "something changed" flag, pulls the
> >> 	update if there is no "editing" flag, clears "changed" flag
> > 
> > I don't want it to have sub-second granularity,
> 
> Ok, I was interpolating, sorry if I misinterpreted your intentions.
> 
> > I just want to make
> > 'crontab -e' more reliable so that cron doesn't miss edits.  cron is
> > currently using the mod-time of the spool directory as the 'something
> > changed' flag (have you read the cron code?).
> 
> I understand the spool behavior from history/experience, and I am
> relying on your excellent summary for the details. :)
> 
> > The problem is that it
> > currently can set the 'something changed' flag non-atomically while it is
> > updating a crontab.
> 
> That much I understood from your post. My response to what it is I think
> you're trying to achieve is that it's not likely that you can achieve it
> by only using 1 flag, no matter what that 1 flag is. I may be wrong
> about that, but hopefully my suggestion gives you some other ideas to
> consider.
> 
> Meanwhile, I was thinking more about this and TMK cron doesn't actually
> *run* jobs with seconds granularity, only minutes, right?  If so then it
> seems that the only really important seconds to care about are :59 and
> :00. That would seem to present a solution that rather than having cron
> wake up every second to see if something has changed that it only do
> that at :59 (or however many seconds in advance of :00 that it needs,
> although if it's more than 1 I'll be surprised). That limits the race to
> someone who writes out a new crontab entry at the point during second
> :59 that is after cron wakes up to look but before :00. So that's not a
> perfect solution to your problem, but it should limit the race to a very
> narrow window without having to modify the code very much.
> 
> 
> hth,
> 
> Doug

I think part of the problem here is that I started typing without
thinking enough... I thought I was offering a different small change
that fixed more than one problem, but it was wrong.  My mistake seems to
be having the unintended effect of sidetracking a perfectly reasonable
small fix for a problem that's known to happen in the real world, just
because it doesn't also fix a theoretical problem that might happen
somewhere some day; that sure wasn't my intention.

-- Ian
Received on Fri Feb 03 2012 - 00:45:02 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:23 UTC