NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: lib/60324: unwind.h build race condition



The following reply was made to PR lib/60324; it has been noted by GNATS.

From: Robert Elz <kre%munnari.OZ.AU@localhost>
To: matthew green <mrg%eterna23.net@localhost>
Cc: gnats-bugs%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost
Subject: Re: lib/60324: unwind.h build race condition
Date: Thu, 09 Jul 2026 10:17:04 +0700

     Date:        Thu, 09 Jul 2026 11:11:26 +1000
     From:        matthew green <mrg%eterna23.net@localhost>
     Message-ID:  <88.1783559486%splode.eterna23.net@localhost>
 
   | maybe the real fix is to not enter this subdirectory twice in
   | this same high-level .WAIT group at all.
 
 The issue with that, for me anyway, was still allowing users
 to cd to anywhere in the tree, and run "make" and have things
 work.   If building libc doesn't (when needed) get the correct
 bits from libgcc (or whatever it was doing), then just
 	cd src/lib/libc; make
 won't necessarily work.  It should.  And so should
 	cd src/external/gpl3/gcc; make
 so both of those need to (at least be able to) descend into the
 part of the tree where the issue occurred (libgcov).
 
   | this isn't the only one, but maybe it's the only one that has
   | a build-a-file conflict.
 
 It might just be because of using ln -- most other commands would just
 replace whatever is there, whereas ln fails if the dest exists, it
 could be switched to use ln -f, but I doubt that's sufficient,
 it still ends up doing a symlink() call, just after (yet another)
 unlink() perhaps, but the two ln(1)'s both doing an unlink() if needed,
 followed by a symlink() in parallel are going to fail in just the same
 way - perhaps slightly less often as the sync between the two would need
 to be tighter.
 
 One possibility I thought of, but didn't try, would be to make the
 ln line of the relevant make recipe be (something like)
 
 	ln -s ${.ALLSRC} ${.TARGET} || \
 		 { X=$(readlink ${.TARGET}) && [ "$X" = "${.ALLSRC}" ] ; }
 
 converted into the correct make syntax ($$X for $X and the cmdsub etc) and
 with someone who knows how checking that the uses of TARGET and ALLSRC are
 correct.
 
 I didn't attempt that, as I never found where the relevant recipe appears
 (somewhere in share/mk I'd assume - a cesspit I like to avoid), and I'm
 also not sure that a change there like this would be OK for every possible
 use (if ever used to link multiple files into a directory, this wouldn't
 work at all).
 
 It also would mean needing readlink as a tool, which I doubt we have now
 (might need to be a specialised version, making stat(1) (which is what our
 readlink(1) really is) into a tool could be a challenge, but a very simple,
 portable, readlink(1), with limited abilities, just enough for this special
 case, should be easy enough).
 
 Or we could toolize ln, and give it a new option, that if set, and an
 EEXIST error is reported, would readlink(2) the existing file, and if that
 works, and the result is the same as the link that was to be created, to
 just treat that as OK, and not fail (which is more or less doing the above,
 internal to ln).   (Might also want to do permission & ownership checks).
 
   | not doing this would mean we could take the new .WAIT away again.
 
 Perhaps.   I'm not sure that would make any real difference, the build
 time for a full set of builds doesn't seem to have been altered, and
 for all the builds I checked (where the info is available without needing
 to do it myself!) the number of lines in the build logfile didn't change
 out of the range that had existed from recent previous builds, so I don't
 think adding that .WAIT really harmed anything - I had half expected the
 builds to take a bit longer, but they don't seem to have.
 
 Of course, it is also possible that the .WAIT is largely a no-op, but from
 what I could tell from my own test builds when I inserted it, it did seem
 to make (for each phase: obj, includes, dependall) the lib builds to be
 complete before the rest of the tree started.    That's where I became
 confused, without the .WAIT there, what was stopping a dependall of (say)
 bin/cat from starting before the new lib/libc is available?   If there is
 (was) nothing preventing that, how does (did) anything actually work?  But
 clearly it all does, and did before, at least 99% of the time.
 
 kre
 
 ps: I am also still not convinced that the problem is fixed, it is likely
 that the cases I detected will no longer occur, but the same thing might
 be possible from a two parts of the tree not including "lib" - just perhaps
 even more rarely occurring.
 
 



Home | Main Index | Thread Index | Old Index