From owner-freebsd-current@FreeBSD.ORG Fri Feb 3 01:03:13 2012 Return-Path: Delivered-To: current@freebsd.org Received: from mx2.freebsd.org (mx2.freebsd.org [IPv6:2001:4f8:fff6::35]) by hub.freebsd.org (Postfix) with ESMTP id D3E071065689; Fri, 3 Feb 2012 01:03:13 +0000 (UTC) (envelope-from dougb@FreeBSD.org) Received: from 172-17-150-251.globalsuite.net (hub.freebsd.org [IPv6:2001:4f8:fff6::36]) by mx2.freebsd.org (Postfix) with ESMTP id 19A0F155312; Fri, 3 Feb 2012 01:03:12 +0000 (UTC) Message-ID: <4F2B3250.7000000@FreeBSD.org> Date: Thu, 02 Feb 2012 17:03:12 -0800 From: Doug Barton Organization: http://SupersetSolutions.com/ User-Agent: Mozilla/5.0 (X11; FreeBSD i386; rv:10.0) Gecko/20120201 Thunderbird/10.0 MIME-Version: 1.0 To: John Baldwin References: <201201311149.32760.jhb@freebsd.org> <4F28A210.90303@FreeBSD.org> <201202010742.11936.jhb@freebsd.org> In-Reply-To: <201202010742.11936.jhb@freebsd.org> X-Enigmail-Version: 1.3.5 OpenPGP: id=1A1ABC84 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Cc: current@freebsd.org Subject: Re: Race between cron and crontab X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Feb 2012 01:03:14 -0000 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/