Re: [PATCH v2 1/3] t/lib-httpd: fix apply-one-time-script race under concurrent requests
Patrick Steinhardt <[email protected]> Tue, 4 Aug 2026 10:03:12 +0200
| Newsgroups | org.kernel.vger.git |
|---|---|
| Message-ID | <[email protected]> |
On Fri, Jul 10, 2026 at 05:30:55PM +0000, Michael Montalbo via GitGitGadget wrote: > diff --git a/t/lib-httpd/apply-one-time-script.sh b/t/lib-httpd/apply-one-time-script.sh > index b1682944e2..adb9cec528 100644 > --- a/t/lib-httpd/apply-one-time-script.sh > +++ b/t/lib-httpd/apply-one-time-script.sh > @@ -6,21 +6,37 @@ > # > # This can be used to simulate the effects of the repository changing in > # between HTTP request-response pairs. > -if test -f one-time-script > -then > - LC_ALL=C > - export LC_ALL > +# > +# Apache can run this CGI for concurrent requests (for example a partial fetch > +# that lazily fetches a missing object while the first response is still in > +# flight), so the helper claims the marker atomically with a rename, and only > +# once it has decided to modify the response. A request that loses the race > +# finds the marker already gone and serves its response unchanged; no request > +# is left emitting an empty body, which the server would report as HTTP 500. > +# Scratch files are per-request ($$) so concurrent requests do not clobber each > +# other. > +# > +# The script may run more than once: the marker is consumed when the response > +# actually changes (the rename after "cmp"), not when the script runs, so a > +# request whose response is not the targeted one runs the script, sees no > +# change, and leaves the marker for a later request. That is safe because the > +# scripts are stateless filters over the captured response. > > - "$GIT_EXEC_PATH/git-http-backend" >out > - ./one-time-script out >out_modified > +test -f one-time-script || exec "$GIT_EXEC_PATH/git-http-backend" > > - if cmp -s out out_modified > - then > - cat out > - else > - cat out_modified > - rm one-time-script > - fi > +LC_ALL=C > +export LC_ALL > + > +out=out.$$ > +modified=out-modified.$$ > +"$GIT_EXEC_PATH/git-http-backend" >"$out" > + > +if ./one-time-script "$out" 2>/dev/null >"$modified" && Is it intentional that we swallow stderr of this script now? We didn't before. I assume that this is to swallow the error in case the script got removed by the concurrent request? Patrick