Subject: Re: bug#10470: MSYS: race in directory access?

From: Peter Rosin <[email-masked]>
Date: Tue, 10 Jan 2012 16:28:15 +0100

Stefano Lattarini skrev 2012-01-10 16:02:
> On 01/10/2012 02:13 PM, Peter Rosin wrote:
>> Stefano Lattarini skrev 2012-01-10 13:44:
>>> On 01/10/2012 12:35 PM, Peter Rosin wrote:
>>>>
>>>> One further data point; changing that "( sleep 1 ) &" thing followed by a
>>>> wait just before AC_OUTPUT into an inlined sleep also fixes the test case.
>>>>
>>> Thanks for tracking this down.  So the question now becomes: why doesn't
>>> the trick with background processes work on MSYS?  Does maybe MSYS lack
>>> proper emulation of POSIX-ish PIDs?  If that is the case, can we easily
>>> work around that in our situation?
>>
>> No no, that's not the problem.  In this case "make distcheck" runs
>> configure, but configure fails so it never reaches AC_OUTPUT and
>> the wait call never happens.
>>
> Ah, good catch.  So the problem is not limited to MinGW, but could potentially
> hit also when we are building on (say) NFS mounts, right?

I don't know how bad it is to try to remove the CWD of another process
for non-MSYS systems, so I can't offer any input on this one.

>> So, the ( sleep 1 ) subshell lives on
>> and "locks" the directory (but something else is also going on,
>> because changing the subshell to do ( cd /; sleep 1 ) doesn't help).
>>
>> *pling* new mail, from Eric.
>>
>> He explains the issue with different words and suggests:
>>
>> "As for what somewhere/safe should be, $(abs_builddir) is probably
>>  reasonable."
>>
>> So, testing that too, but neither cd /, nor cd "$(abs_builddir)" make
>> the test pass. Crap.
>>
> It would probably be worthwhile to try to understand why this is the case.
> As a wild guess, would this work?
> 
>   - ( sleep 1 ) &
>   + sh -c "cd '$abs_builddir'; sleep 1" &

No, fails in the same way as the original.

>> We could fix it in the testsuite only, by adding a trap to configure
>> that does the wait if it didn't happen before, but that would make
>> use of internals that would perhaps spread. Yuck again.
>>
> Or we could enhance your original workaround like this:
> 
>  am__remove_distdir = \
>    { test ! -d "$(distdir)" \
>      || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
> -         && rm -fr "$(distdir)"; }; }
> +         && if rm -fr "$(distdir)"; then :; else \
> +## On MSYS (1.0.17) it is not possible to remove a directory that is
> +## in use; so, if the first rm fails, we sleep some seconds and retry,
> +## to give pending processes some time to exit and "release" the
> +## directory before we removed.  See automake bug#10470.
> +              sleep 5 && rm -fr "$(distdir)"; fi; }; }
>  am__post_remove_distdir = $(am__remove_distdir)
>  endif %?TOPDIR_P%

This works, best so far!  Committable, if you ask me.

Cheers,
Peter