[EMAIL PROTECTED] (Bob Proulx) writes:

> Roger Leigh wrote:
>> Michael Stone <[EMAIL PROTECTED]> writes:
>> > Roger Leigh wrote:
>> >>1) The file can be unlinked by another process in between the stat and
>> >>   the unlink, causing the unlink to fail.  ln should be aware this
>> >>   can happen, and not treat this as a fatal error.
>> >
>> > Why?
>> 
>> Because otherwise the command fails when it should not:
>
> I don't think there ever has been a promise that these commands have
> atomic behavior.

OK.

> If you have suggestions as to how to improve the behavior I am sure
> that would be appreciated.  But I don't see how this can be made
> atomic.  And this does not seem like something to be fixed simply.

I'm not sure if it should or not be fixed, and if fixed, whether it
should or should not be atomic.  I just wanted to report the existence
of the problem.

I'm not sure that (filesystem) atomicity is necessarily required.  The
important thing (for me) is that it succeeds without error unless
there's a real failure (such as permissions issues).  If that means
repeated unlinking until symlink succeeds, that's OK for me: that's
why I used the "-f" switch, because it's OK for the file to be
clobbered.

If this is undesirable, feel free to close or downgrade the severity.
I'm not sure how this would fit in with POSIX/SUS; if it doesn't fit,
it's obviously a broken idea.

>> This *is* a real problem, which we are seeing with the sbuild part of
>> buildd.  It has (perl):
>> 
>>   system "/bin/ln -sf $main::pkg_logfile 
>> $conf::build_dir/current-$main::distribution";
>>   system "/bin/ln -sf $main::pkg_logfile $conf::build_dir/current";
>
> Ew, that is ugly.  And why the hard coded paths?

The hard-coded paths are just for testing (in case ln was a sh
builtin).  I know it's really ugly: I didn't write it myself, and I
will be replacing it shortly with proper perl.

The reason this is done is that the "current" symlink points to the
currently running build log, so you could e.g. tail it to monitor the
current build.  When more than one build is running, it points to the
most recently started one, but when they start at almost exactly the
same time, this is when the race is seen.

> If you need an atomic operation then you will need to use a command
> that is atomic such as rename(2) accessable from within mv.  Here is
> an example in shell off the top of my head but expecting to use a
> better temporary name than the one I just produced for this example.
>
>   ln -sf $pkg_logfile $build_dir/current-$distribution.$$
>   mv $build_dir/current-$distribution.$$ $build_dir/current-$distribution
>
> But of course you are in perl and can access rename from perl even
> more directly.

Absolutely.  I'll be doing just that.  Or even just unlink and symlink
and continuing on error: in this case, it's not so important that it
succeeds, just that the current symlink exists and points to the
latest build.  If it fails, it's because it got preempted by another
build, so that's OK.

> Let me suggest the following instead:
>
>   unlink($conf::build_dir/current-$main::distribution);
>   symlink($main::pkg_logfile,$conf::build_dir/current-$main::distribution.$$) 
> or die;
>   
> rename($conf::build_dir/current-$main::distribution.$$,$conf::build_dir/current-$main::distribution)
>  or die;
>
> I tested the principle using this script.
>
>   #!/usr/bin/perl
>   unlink($ARGV[1].$$);
>   symlink($ARGV[0],$ARGV[1].$$) || die;
>   rename($ARGV[1].$$,$ARGV[1]) || die;

I'll probably just use || return.

Thanks for the suggestions, guys.


Regards,
Roger

-- 
Roger Leigh
                Printing on GNU/Linux?  http://gutenprint.sourceforge.net/
                Debian GNU/Linux        http://www.debian.org/
                GPG Public Key: 0x25BFB848.  Please sign and encrypt your mail.

Attachment: pgpUbwwiQ9Hgo.pgp
Description: PGP signature

Reply via email to