Race between cron and crontab
Doug Barton
dougb at FreeBSD.org
Fri Feb 3 01:03:14 UTC 2012
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
--
It's always a long day; 86400 doesn't fit into a short.
Breadth of IT experience, and depth of knowledge in the DNS.
Yours for the right price. :) http://SupersetSolutions.com/
More information about the freebsd-current
mailing list