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

From: Stefano Lattarini <[email-masked]>
Date: Tue, 10 Jan 2012 16:02:57 +0100

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?

> 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" &

> 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%

Thanks,
  Stefano