* Help needed on 2.54.0-rc0 t5301.13 looping.
@ 2026-04-07 23:37 rsbecker
2026-04-08 5:20 ` Jeff King
0 siblings, 1 reply; 18+ messages in thread
From: rsbecker @ 2026-04-07 23:37 UTC (permalink / raw)
To: git
Weird fail on t5401.13. Any opinions or advise on this?
expecting success of 5401.13 'pre-receive hook that forgets to read its
input':
test_hook --clobber -C victim.git pre-receive <<-\EOF &&
exit 0
EOF
rm -f victim.git/hooks/update victim.git/hooks/post-update &&
test_seq -f "create refs/heads/branch_%d main" 100 999 |
git update-ref --stdin &&
git push ./victim.git "+refs/heads/*:refs/heads/*"
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To ./victim.git
! [remote rejected] tofail -> tofail (pre-receive hook declined)
! [remote rejected] branch_100 -> branch_100 (pre-receive hook declined)
! [remote rejected] branch_101 -> branch_101 (pre-receive hook declined)
! [remote rejected] branch_102 -> branch_102 (pre-receive hook declined)
! [remote rejected] branch_103 -> branch_103 (pre-receive hook declined)
! [remote rejected] branch_104 -> branch_104 (pre-receive hook declined)
! [remote rejected] branch_105 -> branch_105 (pre-receive hook declined)
! [remote rejected] branch_106 -> branch_106 (pre-receive hook declined)
! [remote rejected] branch_107 -> branch_107 (pre-receive hook declined)
! [remote rejected] branch_108 -> branch_108 (pre-receive hook declined)
! [remote rejected] branch_109 -> branch_109 (pre-receive hook declined)
! [remote rejected] branch_110 -> branch_110 (pre-receive hook declined)
! [remote rejected] branch_111 -> branch_111 (pre-receive hook declined)
! [remote rejected] branch_112 -> branch_112 (pre-receive hook declined)
! [remote rejected] branch_113 -> branch_113 (pre-receive hook declined)
! [remote rejected] branch_114 -> branch_114 (pre-receive hook declined)
! [remote rejected] branch_115 -> branch_115 (pre-receive hook declined)
! [remote rejected] branch_116 -> branch_116 (pre-receive hook declined)
! [remote rejected] branch_117 -> branch_117 (pre-receive hook declined)
! [remote rejected] branch_118 -> branch_118 (pre-receive hook declined)
! [remote rejected] branch_119 -> branch_119 (pre-receive hook declined)
! [remote rejected] branch_120 -> branch_120 (pre-receive hook declined)
! [remote rejected] branch_121 -> branch_121 (pre-receive hook declined)
! [remote rejected] branch_122 -> branch_122 (pre-receive hook declined)
! [remote rejected] branch_123 -> branch_123 (pre-receive hook declined)
! [remote rejected] branch_124 -> branch_124 (pre-receive hook declined)
! [remote rejected] branch_125 -> branch_125 (pre-receive hook declined)
! [remote rejected] branch_126 -> branch_126 (pre-receive hook declined)
! [remote rejected] branch_127 -> branch_127 (pre-receive hook declined)
! [remote rejected] branch_128 -> branch_128 (pre-receive hook declined)
! [remote rejected] branch_129 -> branch_129 (pre-receive hook declined)
! [remote rejected] branch_130 -> branch_130 (pre-receive hook declined)
! [remote rejected] branch_131 -> branch_131 (pre-receive hook declined)
! [remote rejected] branch_132 -> branch_132 (pre-receive hook declined)
! [remote rejected] branch_133 -> branch_133 (pre-receive hook declined)
! [remote rejected] branch_134 -> branch_134 (pre-receive hook declined)
! [remote rejected] branch_135 -> branch_135 (pre-receive hook declined)
! [remote rejected] branch_136 -> branch_136 (pre-receive hook declined)
! [remote rejected] branch_137 -> branch_137 (pre-receive hook declined)
! [remote rejected] branch_138 -> branch_138 (pre-receive hook declined)
! [remote rejected] branch_139 -> branch_139 (pre-receive hook declined)
! [remote rejected] branch_140 -> branch_140 (pre-receive hook declined)
! [remote rejected] branch_141 -> branch_141 (pre-receive hook declined)
! [remote rejected] branch_142 -> branch_142 (pre-receive hook declined)
! [remote rejected] branch_143 -> branch_143 (pre-receive hook declined)
! [remote rejected] branch_144 -> branch_144 (pre-receive hook declined)
! [remote rejected] branch_145 -> branch_145 (pre-receive hook declined)
! [remote rejected] branch_146 -> branch_146 (pre-receive hook declined)
! [remote rejected] branch_147 -> branch_147 (pre-receive hook declined)
! [remote rejected] branch_148 -> branch_148 (pre-receive hook declined)
! [remote rejected] branch_149 -> branch_149 (pre-receive hook declined)
! [remote rejected] branch_150 -> branch_150 (pre-receive hook declined)
! [remote rejected] branch_151 -> branch_151 (pre-receive hook declined)
! [remote rejected] branch_152 -> branch_152 (pre-receive hook declined)
! [remote rejected] branch_153 -> branch_153 (pre-receive hook declined)
! [remote rejected] branch_154 -> branch_154 (pre-receive hook declined)
! [remote rejected] branch_155 -> branch_155 (pre-receive hook declined)
! [remote rejected] branch_156 -> branch_156 (pre-receive hook declined)
! [remote rejected] branch_157 -> branch_157 (pre-receive hook declined)
! [remote rejected] branch_158 -> branch_158 (pre-receive hook declined)
! [remote rejected] branch_159 -> branch_159 (pre-receive hook declined)
! [remote rejected] branch_160 -> branch_160 (pre-receive hook declined)
! [remote rejected] branch_161 -> branch_161 (pre-receive hook declined)
! [remote rejected] branch_162 -> branch_162 (pre-receive hook declined)
! [remote rejected] branch_163 -> branch_163 (pre-receive hook declined)
! [remote rejected] branch_164 -> branch_164 (pre-receive hook declined)
! [remote rejected] branch_165 -> branch_165 (pre-receive hook declined)
! [remote rejected] branch_166 -> branch_166 (pre-receive hook declined)
! [remote rejected] branch_167 -> branch_167 (pre-receive hook declined)
! [remote rejected] branch_168 -> branch_168 (pre-receive hook declined)
! [remote rejected] branch_169 -> branch_169 (pre-receive hook declined)
! [remote rejected] branch_170 -> branch_170 (pre-receive hook declined)
! [remote rejected] branch_171 -> branch_171 (pre-receive hook declined)
! [remote rejected] branch_172 -> branch_172 (pre-receive hook declined)
! [remote rejected] branch_173 -> branch_173 (pre-receive hook declined)
! [remote rejected] branch_174 -> branch_174 (pre-receive hook declined)
! [remote rejected] branch_175 -> branch_175 (pre-receive hook declined)
! [remote rejected] branch_176 -> branch_176 (pre-receive hook declined)
! [remote rejected] branch_177 -> branch_177 (pre-receive hook declined)
! [remote rejected] branch_178 -> branch_178 (pre-receive hook declined)
! [remote rejected] branch_179 -> branch_179 (pre-receive hook declined)
! [remote rejected] branch_180 -> branch_180 (pre-receive hook declined)
! [remote rejected] branch_181 -> branch_181 (pre-receive hook declined)
! [remote rejected] branch_182 -> branch_182 (pre-receive hook declined)
! [remote rejected] branch_183 -> branch_183 (pre-receive hook declined)
! [remote rejected] branch_184 -> branch_184 (pre-receive hook declined)
! [remote rejected] branch_185 -> branch_185 (pre-receive hook declined)
! [remote rejected] branch_186 -> branch_186 (pre-receive hook declined)
! [remote rejected] branch_187 -> branch_187 (pre-receive hook declined)
! [remote rejected] branch_188 -> branch_188 (pre-receive hook declined)
! [remote rejected] branch_189 -> branch_189 (pre-receive hook declined)
! [remote rejected] branch_190 -> branch_190 (pre-receive hook declined)
! [remote rejected] branch_191 -> branch_191 (pre-receive hook declined)
! [remote rejected] branch_192 -> branch_192 (pre-receive hook declined)
! [remote rejected] branch_193 -> branch_193 (pre-receive hook declined)
! [remote rejected] branch_194 -> branch_194 (pre-receive hook declined)
! [remote rejected] branch_195 -> branch_195 (pre-receive hook declined)
! [remote rejected] branch_196 -> branch_196 (pre-receive hook declined)
! [remote rejected] branch_197 -> branch_197 (pre-receive hook declined)
! [remote rejected] branch_198 -> branch_198 (pre-receive hook declined)
! [remote rejected] branch_199 -> branch_199 (pre-receive hook declined)
! [remote rejected] branch_200 -> branch_200 (pre-receive hook declined)
! [remote rejected] branch_201 -> branch_201 (pre-receive hook declined)
! [remote rejected] branch_202 -> branch_202 (pre-receive hook declined)
! [remote rejected] branch_203 -> branch_203 (pre-receive hook declined)
! [remote rejected] branch_204 -> branch_204 (pre-receive hook declined)
! [remote rejected] branch_205 -> branch_205 (pre-receive hook declined)
! [remote rejected] branch_206 -> branch_206 (pre-receive hook declined)
! [remote rejected] branch_207 -> branch_207 (pre-receive hook declined)
! [remote rejected] branch_208 -> branch_208 (pre-receive hook declined)
! [remote rejected] branch_209 -> branch_209 (pre-receive hook declined)
! [remote rejected] branch_210 -> branch_210 (pre-receive hook declined)
! [remote rejected] branch_211 -> branch_211 (pre-receive hook declined)
! [remote rejected] branch_212 -> branch_212 (pre-receive hook declined)
! [remote rejected] branch_213 -> branch_213 (pre-receive hook declined)
! [remote rejected] branch_214 -> branch_214 (pre-receive hook declined)
! [remote rejected] branch_215 -> branch_215 (pre-receive hook declined)
! [remote rejected] branch_216 -> branch_216 (pre-receive hook declined)
! [remote rejected] branch_217 -> branch_217 (pre-receive hook declined)
! [remote rejected] branch_218 -> branch_218 (pre-receive hook declined)
! [remote rejected] branch_219 -> branch_219 (pre-receive hook declined)
! [remote rejected] branch_220 -> branch_220 (pre-receive hook declined)
! [remote rejected] branch_221 -> branch_221 (pre-receive hook declined)
! [remote rejected] branch_222 -> branch_222 (pre-receive hook declined)
! [remote rejected] branch_223 -> branch_223 (pre-receive hook declined)
! [remote rejected] branch_224 -> branch_224 (pre-receive hook declined)
! [remote rejected] branch_225 -> branch_225 (pre-receive hook declined)
! [remote rejected] branch_226 -> branch_226 (pre-receive hook declined)
! [remote rejected] branch_227 -> branch_227 (pre-receive hook declined)
! [remote rejected] branch_228 -> branch_228 (pre-receive hook declined)
! [remote rejected] branch_229 -> branch_229 (pre-receive hook declined)
! [remote rejected] branch_230 -> branch_230 (pre-receive hook declined)
! [remote rejected] branch_231 -> branch_231 (pre-receive hook declined)
! [remote rejected] branch_232 -> branch_232 (pre-receive hook declined)
! [remote rejected] branch_233 -> branch_233 (pre-receive hook declined)
! [remote rejected] branch_234 -> branch_234 (pre-receive hook declined)
! [remote rejected] branch_235 -> branch_235 (pre-receive hook declined)
! [remote rejected] branch_236 -> branch_236 (pre-receive hook declined)
! [remote rejected] branch_237 -> branch_237 (pre-receive hook declined)
! [remote rejected] branch_238 -> branch_238 (pre-receive hook declined)
! [remote rejected] branch_239 -> branch_239 (pre-receive hook declined)
! [remote rejected] branch_240 -> branch_240 (pre-receive hook declined)
! [remote rejected] branch_241 -> branch_241 (pre-receive hook declined)
! [remote rejected] branch_242 -> branch_242 (pre-receive hook declined)
! [remote rejected] branch_243 -> branch_243 (pre-receive hook declined)
! [remote rejected] branch_244 -> branch_244 (pre-receive hook declined)
! [remote rejected] branch_245 -> branch_245 (pre-receive hook declined)
! [remote rejected] branch_246 -> branch_246 (pre-receive hook declined)
! [remote rejected] branch_247 -> branch_247 (pre-receive hook declined)
! [remote rejected] branch_248 -> branch_248 (pre-receive hook declined)
! [remote rejected] branch_249 -> branch_249 (pre-receive hook declined)
! [remote rejected] branch_250 -> branch_250 (pre-receive hook declined)
! [remote rejected] branch_251 -> branch_251 (pre-receive hook declined)
! [remote rejected] branch_252 -> branch_252 (pre-receive hook declined)
! [remote rejected] branch_253 -> branch_253 (pre-receive hook declined)
! [remote rejected] branch_254 -> branch_254 (pre-receive hook declined)
! [remote rejected] branch_255 -> branch_255 (pre-receive hook declined)
! [remote rejected] branch_256 -> branch_256 (pre-receive hook declined)
! [remote rejected] branch_257 -> branch_257 (pre-receive hook declined)
! [remote rejected] branch_258 -> branch_258 (pre-receive hook declined)
! [remote rejected] branch_259 -> branch_259 (pre-receive hook declined)
! [remote rejected] branch_260 -> branch_260 (pre-receive hook declined)
! [remote rejected] branch_261 -> branch_261 (pre-receive hook declined)
! [remote rejected] branch_262 -> branch_262 (pre-receive hook declined)
! [remote rejected] branch_263 -> branch_263 (pre-receive hook declined)
! [remote rejected] branch_264 -> branch_264 (pre-receive hook declined)
! [remote rejected] branch_265 -> branch_265 (pre-receive hook declined)
! [remote rejected] branch_266 -> branch_266 (pre-receive hook declined)
! [remote rejected] branch_267 -> branch_267 (pre-receive hook declined)
! [remote rejected] branch_268 -> branch_268 (pre-receive hook declined)
! [remote rejected] branch_269 -> branch_269 (pre-receive hook declined)
! [remote rejected] branch_270 -> branch_270 (pre-receive hook declined)
! [remote rejected] branch_271 -> branch_271 (pre-receive hook declined)
! [remote rejected] branch_272 -> branch_272 (pre-receive hook declined)
! [remote rejected] branch_273 -> branch_273 (pre-receive hook declined)
! [remote rejected] branch_274 -> branch_274 (pre-receive hook declined)
! [remote rejected] branch_275 -> branch_275 (pre-receive hook declined)
! [remote rejected] branch_276 -> branch_276 (pre-receive hook declined)
! [remote rejected] branch_277 -> branch_277 (pre-receive hook declined)
! [remote rejected] branch_278 -> branch_278 (pre-receive hook declined)
! [remote rejected] branch_279 -> branch_279 (pre-receive hook declined)
! [remote rejected] branch_280 -> branch_280 (pre-receive hook declined)
! [remote rejected] branch_281 -> branch_281 (pre-receive hook declined)
! [remote rejected] branch_282 -> branch_282 (pre-receive hook declined)
! [remote rejected] branch_283 -> branch_283 (pre-receive hook declined)
! [remote rejected] branch_284 -> branch_284 (pre-receive hook declined)
! [remote rejected] branch_285 -> branch_285 (pre-receive hook declined)
! [remote rejected] branch_286 -> branch_286 (pre-receive hook declined)
! [remote rejected] branch_287 -> branch_287 (pre-receive hook declined)
! [remote rejected] branch_288 -> branch_288 (pre-receive hook declined)
! [remote rejected] branch_289 -> branch_289 (pre-receive hook declined)
! [remote rejected] branch_290 -> branch_290 (pre-receive hook declined)
! [remote rejected] branch_291 -> branch_291 (pre-receive hook declined)
! [remote rejected] branch_292 -> branch_292 (pre-receive hook declined)
! [remote rejected] branch_293 -> branch_293 (pre-receive hook declined)
! [remote rejected] branch_294 -> branch_294 (pre-receive hook declined)
! [remote rejected] branch_295 -> branch_295 (pre-receive hook declined)
! [remote rejected] branch_296 -> branch_296 (pre-receive hook declined)
! [remote rejected] branch_297 -> branch_297 (pre-receive hook declined)
! [remote rejected] branch_298 -> branch_298 (pre-receive hook declined)
! [remote rejected] branch_299 -> branch_299 (pre-receive hook declined)
! [remote rejected] branch_300 -> branch_300 (pre-receive hook declined)
! [remote rejected] branch_301 -> branch_301 (pre-receive hook declined)
! [remote rejected] branch_302 -> branch_302 (pre-receive hook declined)
! [remote rejected] branch_303 -> branch_303 (pre-receive hook declined)
! [remote rejected] branch_304 -> branch_304 (pre-receive hook declined)
! [remote rejected] branch_305 -> branch_305 (pre-receive hook declined)
! [remote rejected] branch_306 -> branch_306 (pre-receive hook declined)
! [remote rejected] branch_307 -> branch_307 (pre-receive hook declined)
! [remote rejected] branch_308 -> branch_308 (pre-receive hook declined)
! [remote rejected] branch_309 -> branch_309 (pre-receive hook declined)
! [remote rejected] branch_310 -> branch_310 (pre-receive hook declined)
! [remote rejected] branch_311 -> branch_311 (pre-receive hook declined)
! [remote rejected] branch_312 -> branch_312 (pre-receive hook declined)
! [remote rejected] branch_313 -> branch_313 (pre-receive hook declined)
! [remote rejected] branch_314 -> branch_314 (pre-receive hook declined)
! [remote rejected] branch_315 -> branch_315 (pre-receive hook declined)
! [remote rejected] branch_316 -> branch_316 (pre-receive hook declined)
! [remote rejected] branch_317 -> branch_317 (pre-receive hook declined)
! [remote rejected] branch_318 -> branch_318 (pre-receive hook declined)
! [remote rejected] branch_319 -> branch_319 (pre-receive hook declined)
! [remote rejected] branch_320 -> branch_320 (pre-receive hook declined)
! [remote rejected] branch_321 -> branch_321 (pre-receive hook declined)
! [remote rejected] branch_322 -> branch_322 (pre-receive hook declined)
! [remote rejected] branch_323 -> branch_323 (pre-receive hook declined)
! [remote rejected] branch_324 -> branch_324 (pre-receive hook declined)
! [remote rejected] branch_325 -> branch_325 (pre-receive hook declined)
! [remote rejected] branch_326 -> branch_326 (pre-receive hook declined)
! [remote rejected] branch_327 -> branch_327 (pre-receive hook declined)
! [remote rejected] branch_328 -> branch_328 (pre-receive hook declined)
! [remote rejected] branch_329 -> branch_329 (pre-receive hook declined)
! [remote rejected] branch_330 -> branch_330 (pre-receive hook declined)
! [remote rejected] branch_331 -> branch_331 (pre-receive hook declined)
! [remote rejected] branch_332 -> branch_332 (pre-receive hook declined)
! [remote rejected] branch_333 -> branch_333 (pre-receive hook declined)
! [remote rejected] branch_334 -> branch_334 (pre-receive hook declined)
! [remote rejected] branch_335 -> branch_335 (pre-receive hook declined)
! [remote rejected] branch_336 -> branch_336 (pre-receive hook declined)
! [remote rejected] branch_337 -> branch_337 (pre-receive hook declined)
! [remote rejected] branch_338 -> branch_338 (pre-receive hook declined)
! [remote rejected] branch_339 -> branch_339 (pre-receive hook declined)
! [remote rejected] branch_340 -> branch_340 (pre-receive hook declined)
! [remote rejected] branch_341 -> branch_341 (pre-receive hook declined)
! [remote rejected] branch_342 -> branch_342 (pre-receive hook declined)
! [remote rejected] branch_343 -> branch_343 (pre-receive hook declined)
! [remote rejected] branch_344 -> branch_344 (pre-receive hook declined)
! [remote rejected] branch_345 -> branch_345 (pre-receive hook declined)
! [remote rejected] branch_346 -> branch_346 (pre-receive hook declined)
! [remote rejected] branch_347 -> branch_347 (pre-receive hook declined)
! [remote rejected] branch_348 -> branch_348 (pre-receive hook declined)
! [remote rejected] branch_349 -> branch_349 (pre-receive hook declined)
! [remote rejected] branch_350 -> branch_350 (pre-receive hook declined)
! [remote rejected] branch_351 -> branch_351 (pre-receive hook declined)
! [remote rejected] branch_352 -> branch_352 (pre-receive hook declined)
! [remote rejected] branch_353 -> branch_353 (pre-receive hook declined)
! [remote rejected] branch_354 -> branch_354 (pre-receive hook declined)
! [remote rejected] branch_355 -> branch_355 (pre-receive hook declined)
! [remote rejected] branch_356 -> branch_356 (pre-receive hook declined)
! [remote rejected] branch_357 -> branch_357 (pre-receive hook declined)
! [remote rejected] branch_358 -> branch_358 (pre-receive hook declined)
! [remote rejected] branch_359 -> branch_359 (pre-receive hook declined)
! [remote rejected] branch_360 -> branch_360 (pre-receive hook declined)
! [remote rejected] branch_361 -> branch_361 (pre-receive hook declined)
! [remote rejected] branch_362 -> branch_362 (pre-receive hook declined)
! [remote rejected] branch_363 -> branch_363 (pre-receive hook declined)
! [remote rejected] branch_364 -> branch_364 (pre-receive hook declined)
! [remote rejected] branch_365 -> branch_365 (pre-receive hook declined)
! [remote rejected] branch_366 -> branch_366 (pre-receive hook declined)
! [remote rejected] branch_367 -> branch_367 (pre-receive hook declined)
! [remote rejected] branch_368 -> branch_368 (pre-receive hook declined)
! [remote rejected] branch_369 -> branch_369 (pre-receive hook declined)
! [remote rejected] branch_370 -> branch_370 (pre-receive hook declined)
! [remote rejected] branch_371 -> branch_371 (pre-receive hook declined)
! [remote rejected] branch_372 -> branch_372 (pre-receive hook declined)
! [remote rejected] branch_373 -> branch_373 (pre-receive hook declined)
! [remote rejected] branch_374 -> branch_374 (pre-receive hook declined)
! [remote rejected] branch_375 -> branch_375 (pre-receive hook declined)
! [remote rejected] branch_376 -> branch_376 (pre-receive hook declined)
! [remote rejected] branch_377 -> branch_377 (pre-receive hook declined)
! [remote rejected] branch_378 -> branch_378 (pre-receive hook declined)
! [remote rejected] branch_379 -> branch_379 (pre-receive hook declined)
! [remote rejected] branch_380 -> branch_380 (pre-receive hook declined)
! [remote rejected] branch_381 -> branch_381 (pre-receive hook declined)
! [remote rejected] branch_382 -> branch_382 (pre-receive hook declined)
! [remote rejected] branch_383 -> branch_383 (pre-receive hook declined)
! [remote rejected] branch_384 -> branch_384 (pre-receive hook declined)
! [remote rejected] branch_385 -> branch_385 (pre-receive hook declined)
! [remote rejected] branch_386 -> branch_386 (pre-receive hook declined)
! [remote rejected] branch_387 -> branch_387 (pre-receive hook declined)
! [remote rejected] branch_388 -> branch_388 (pre-receive hook declined)
! [remote rejected] branch_389 -> branch_389 (pre-receive hook declined)
! [remote rejected] branch_390 -> branch_390 (pre-receive hook declined)
! [remote rejected] branch_391 -> branch_391 (pre-receive hook declined)
! [remote rejected] branch_392 -> branch_392 (pre-receive hook declined)
! [remote rejected] branch_393 -> branch_393 (pre-receive hook declined)
! [remote rejected] branch_394 -> branch_394 (pre-receive hook declined)
! [remote rejected] branch_395 -> branch_395 (pre-receive hook declined)
! [remote rejected] branch_396 -> branch_396 (pre-receive hook declined)
! [remote rejected] branch_397 -> branch_397 (pre-receive hook declined)
! [remote rejected] branch_398 -> branch_398 (pre-receive hook declined)
! [remote rejected] branch_399 -> branch_399 (pre-receive hook declined)
! [remote rejected] branch_400 -> branch_400 (pre-receive hook declined)
! [remote rejected] branch_401 -> branch_401 (pre-receive hook declined)
! [remote rejected] branch_402 -> branch_402 (pre-receive hook declined)
! [remote rejected] branch_403 -> branch_403 (pre-receive hook declined)
! [remote rejected] branch_404 -> branch_404 (pre-receive hook declined)
! [remote rejected] branch_405 -> branch_405 (pre-receive hook declined)
! [remote rejected] branch_406 -> branch_406 (pre-receive hook declined)
! [remote rejected] branch_407 -> branch_407 (pre-receive hook declined)
! [remote rejected] branch_408 -> branch_408 (pre-receive hook declined)
! [remote rejected] branch_409 -> branch_409 (pre-receive hook declined)
! [remote rejected] branch_410 -> branch_410 (pre-receive hook declined)
! [remote rejected] branch_411 -> branch_411 (pre-receive hook declined)
! [remote rejected] branch_412 -> branch_412 (pre-receive hook declined)
! [remote rejected] branch_413 -> branch_413 (pre-receive hook declined)
! [remote rejected] branch_414 -> branch_414 (pre-receive hook declined)
! [remote rejected] branch_415 -> branch_415 (pre-receive hook declined)
! [remote rejected] branch_416 -> branch_416 (pre-receive hook declined)
! [remote rejected] branch_417 -> branch_417 (pre-receive hook declined)
! [remote rejected] branch_418 -> branch_418 (pre-receive hook declined)
! [remote rejected] branch_419 -> branch_419 (pre-receive hook declined)
! [remote rejected] branch_420 -> branch_420 (pre-receive hook declined)
! [remote rejected] branch_421 -> branch_421 (pre-receive hook declined)
! [remote rejected] branch_422 -> branch_422 (pre-receive hook declined)
! [remote rejected] branch_423 -> branch_423 (pre-receive hook declined)
! [remote rejected] branch_424 -> branch_424 (pre-receive hook declined)
! [remote rejected] branch_425 -> branch_425 (pre-receive hook declined)
! [remote rejected] branch_426 -> branch_426 (pre-receive hook declined)
! [remote rejected] branch_427 -> branch_427 (pre-receive hook declined)
! [remote rejected] branch_428 -> branch_428 (pre-receive hook declined)
! [remote rejected] branch_429 -> branch_429 (pre-receive hook declined)
! [remote rejected] branch_430 -> branch_430 (pre-receive hook declined)
! [remote rejected] branch_431 -> branch_431 (pre-receive hook declined)
! [remote rejected] branch_432 -> branch_432 (pre-receive hook declined)
! [remote rejected] branch_433 -> branch_433 (pre-receive hook declined)
! [remote rejected] branch_434 -> branch_434 (pre-receive hook declined)
! [remote rejected] branch_435 -> branch_435 (pre-receive hook declined)
! [remote rejected] branch_436 -> branch_436 (pre-receive hook declined)
! [remote rejected] branch_437 -> branch_437 (pre-receive hook declined)
! [remote rejected] branch_438 -> branch_438 (pre-receive hook declined)
! [remote rejected] branch_439 -> branch_439 (pre-receive hook declined)
! [remote rejected] branch_440 -> branch_440 (pre-receive hook declined)
! [remote rejected] branch_441 -> branch_441 (pre-receive hook declined)
! [remote rejected] branch_442 -> branch_442 (pre-receive hook declined)
! [remote rejected] branch_443 -> branch_443 (pre-receive hook declined)
! [remote rejected] branch_444 -> branch_444 (pre-receive hook declined)
! [remote rejected] branch_445 -> branch_445 (pre-receive hook declined)
! [remote rejected] branch_446 -> branch_446 (pre-receive hook declined)
! [remote rejected] branch_447 -> branch_447 (pre-receive hook declined)
! [remote rejected] branch_448 -> branch_448 (pre-receive hook declined)
! [remote rejected] branch_449 -> branch_449 (pre-receive hook declined)
! [remote rejected] branch_450 -> branch_450 (pre-receive hook declined)
! [remote rejected] branch_451 -> branch_451 (pre-receive hook declined)
! [remote rejected] branch_452 -> branch_452 (pre-receive hook declined)
! [remote rejected] branch_453 -> branch_453 (pre-receive hook declined)
! [remote rejected] branch_454 -> branch_454 (pre-receive hook declined)
! [remote rejected] branch_455 -> branch_455 (pre-receive hook declined)
! [remote rejected] branch_456 -> branch_456 (pre-receive hook declined)
! [remote rejected] branch_457 -> branch_457 (pre-receive hook declined)
! [remote rejected] branch_458 -> branch_458 (pre-receive hook declined)
! [remote rejected] branch_459 -> branch_459 (pre-receive hook declined)
! [remote rejected] branch_460 -> branch_460 (pre-receive hook declined)
! [remote rejected] branch_461 -> branch_461 (pre-receive hook declined)
! [remote rejected] branch_462 -> branch_462 (pre-receive hook declined)
! [remote rejected] branch_463 -> branch_463 (pre-receive hook declined)
! [remote rejected] branch_464 -> branch_464 (pre-receive hook declined)
! [remote rejected] branch_465 -> branch_465 (pre-receive hook declined)
! [remote rejected] branch_466 -> branch_466 (pre-receive hook declined)
! [remote rejected] branch_467 -> branch_467 (pre-receive hook declined)
! [remote rejected] branch_468 -> branch_468 (pre-receive hook declined)
! [remote rejected] branch_469 -> branch_469 (pre-receive hook declined)
! [remote rejected] branch_470 -> branch_470 (pre-receive hook declined)
! [remote rejected] branch_471 -> branch_471 (pre-receive hook declined)
! [remote rejected] branch_472 -> branch_472 (pre-receive hook declined)
! [remote rejected] branch_473 -> branch_473 (pre-receive hook declined)
! [remote rejected] branch_474 -> branch_474 (pre-receive hook declined)
! [remote rejected] branch_475 -> branch_475 (pre-receive hook declined)
! [remote rejected] branch_476 -> branch_476 (pre-receive hook declined)
! [remote rejected] branch_477 -> branch_477 (pre-receive hook declined)
! [remote rejected] branch_478 -> branch_478 (pre-receive hook declined)
! [remote rejected] branch_479 -> branch_479 (pre-receive hook declined)
! [remote rejected] branch_480 -> branch_480 (pre-receive hook declined)
! [remote rejected] branch_481 -> branch_481 (pre-receive hook declined)
! [remote rejected] branch_482 -> branch_482 (pre-receive hook declined)
! [remote rejected] branch_483 -> branch_483 (pre-receive hook declined)
! [remote rejected] branch_484 -> branch_484 (pre-receive hook declined)
! [remote rejected] branch_485 -> branch_485 (pre-receive hook declined)
! [remote rejected] branch_486 -> branch_486 (pre-receive hook declined)
! [remote rejected] branch_487 -> branch_487 (pre-receive hook declined)
! [remote rejected] branch_488 -> branch_488 (pre-receive hook declined)
! [remote rejected] branch_489 -> branch_489 (pre-receive hook declined)
! [remote rejected] branch_490 -> branch_490 (pre-receive hook declined)
! [remote rejected] branch_491 -> branch_491 (pre-receive hook declined)
! [remote rejected] branch_492 -> branch_492 (pre-receive hook declined)
! [remote rejected] branch_493 -> branch_493 (pre-receive hook declined)
! [remote rejected] branch_494 -> branch_494 (pre-receive hook declined)
! [remote rejected] branch_495 -> branch_495 (pre-receive hook declined)
! [remote rejected] branch_496 -> branch_496 (pre-receive hook declined)
! [remote rejected] branch_497 -> branch_497 (pre-receive hook declined)
! [remote rejected] branch_498 -> branch_498 (pre-receive hook declined)
! [remote rejected] branch_499 -> branch_499 (pre-receive hook declined)
! [remote rejected] branch_500 -> branch_500 (pre-receive hook declined)
! [remote rejected] branch_501 -> branch_501 (pre-receive hook declined)
! [remote rejected] branch_502 -> branch_502 (pre-receive hook declined)
! [remote rejected] branch_503 -> branch_503 (pre-receive hook declined)
! [remote rejected] branch_504 -> branch_504 (pre-receive hook declined)
! [remote rejected] branch_505 -> branch_505 (pre-receive hook declined)
! [remote rejected] branch_506 -> branch_506 (pre-receive hook declined)
! [remote rejected] branch_507 -> branch_507 (pre-receive hook declined)
! [remote rejected] branch_508 -> branch_508 (pre-receive hook declined)
! [remote rejected] branch_509 -> branch_509 (pre-receive hook declined)
! [remote rejected] branch_510 -> branch_510 (pre-receive hook declined)
! [remote rejected] branch_511 -> branch_511 (pre-receive hook declined)
! [remote rejected] branch_512 -> branch_512 (pre-receive hook declined)
! [remote rejected] branch_513 -> branch_513 (pre-receive hook declined)
! [remote rejected] branch_514 -> branch_514 (pre-receive hook declined)
! [remote rejected] branch_515 -> branch_515 (pre-receive hook declined)
! [remote rejected] branch_516 -> branch_516 (pre-receive hook declined)
! [remote rejected] branch_517 -> branch_517 (pre-receive hook declined)
! [remote rejected] branch_518 -> branch_518 (pre-receive hook declined)
! [remote rejected] branch_519 -> branch_519 (pre-receive hook declined)
! [remote rejected] branch_520 -> branch_520 (pre-receive hook declined)
! [remote rejected] branch_521 -> branch_521 (pre-receive hook declined)
! [remote rejected] branch_522 -> branch_522 (pre-receive hook declined)
! [remote rejected] branch_523 -> branch_523 (pre-receive hook declined)
! [remote rejected] branch_524 -> branch_524 (pre-receive hook declined)
! [remote rejected] branch_525 -> branch_525 (pre-receive hook declined)
! [remote rejected] branch_526 -> branch_526 (pre-receive hook declined)
! [remote rejected] branch_527 -> branch_527 (pre-receive hook declined)
! [remote rejected] branch_528 -> branch_528 (pre-receive hook declined)
! [remote rejected] branch_529 -> branch_529 (pre-receive hook declined)
! [remote rejected] branch_530 -> branch_530 (pre-receive hook declined)
! [remote rejected] branch_531 -> branch_531 (pre-receive hook declined)
! [remote rejected] branch_532 -> branch_532 (pre-receive hook declined)
! [remote rejected] branch_533 -> branch_533 (pre-receive hook declined)
! [remote rejected] branch_534 -> branch_534 (pre-receive hook declined)
! [remote rejected] branch_535 -> branch_535 (pre-receive hook declined)
! [remote rejected] branch_536 -> branch_536 (pre-receive hook declined)
! [remote rejected] branch_537 -> branch_537 (pre-receive hook declined)
! [remote rejected] branch_538 -> branch_538 (pre-receive hook declined)
! [remote rejected] branch_539 -> branch_539 (pre-receive hook declined)
! [remote rejected] branch_540 -> branch_540 (pre-receive hook declined)
! [remote rejected] branch_541 -> branch_541 (pre-receive hook declined)
! [remote rejected] branch_542 -> branch_542 (pre-receive hook declined)
! [remote rejected] branch_543 -> branch_543 (pre-receive hook declined)
! [remote rejected] branch_544 -> branch_544 (pre-receive hook declined)
! [remote rejected] branch_545 -> branch_545 (pre-receive hook declined)
! [remote rejected] branch_546 -> branch_546 (pre-receive hook declined)
! [remote rejected] branch_547 -> branch_547 (pre-receive hook declined)
! [remote rejected] branch_548 -> branch_548 (pre-receive hook declined)
! [remote rejected] branch_549 -> branch_549 (pre-receive hook declined)
! [remote rejected] branch_550 -> branch_550 (pre-receive hook declined)
! [remote rejected] branch_551 -> branch_551 (pre-receive hook declined)
! [remote rejected] branch_552 -> branch_552 (pre-receive hook declined)
! [remote rejected] branch_553 -> branch_553 (pre-receive hook declined)
! [remote rejected] branch_554 -> branch_554 (pre-receive hook declined)
! [remote rejected] branch_555 -> branch_555 (pre-receive hook declined)
! [remote rejected] branch_556 -> branch_556 (pre-receive hook declined)
! [remote rejected] branch_557 -> branch_557 (pre-receive hook declined)
! [remote rejected] branch_558 -> branch_558 (pre-receive hook declined)
! [remote rejected] branch_559 -> branch_559 (pre-receive hook declined)
! [remote rejected] branch_560 -> branch_560 (pre-receive hook declined)
! [remote rejected] branch_561 -> branch_561 (pre-receive hook declined)
! [remote rejected] branch_562 -> branch_562 (pre-receive hook declined)
! [remote rejected] branch_563 -> branch_563 (pre-receive hook declined)
! [remote rejected] branch_564 -> branch_564 (pre-receive hook declined)
! [remote rejected] branch_565 -> branch_565 (pre-receive hook declined)
! [remote rejected] branch_566 -> branch_566 (pre-receive hook declined)
! [remote rejected] branch_567 -> branch_567 (pre-receive hook declined)
! [remote rejected] branch_568 -> branch_568 (pre-receive hook declined)
! [remote rejected] branch_569 -> branch_569 (pre-receive hook declined)
! [remote rejected] branch_570 -> branch_570 (pre-receive hook declined)
! [remote rejected] branch_571 -> branch_571 (pre-receive hook declined)
! [remote rejected] branch_572 -> branch_572 (pre-receive hook declined)
! [remote rejected] branch_573 -> branch_573 (pre-receive hook declined)
! [remote rejected] branch_574 -> branch_574 (pre-receive hook declined)
! [remote rejected] branch_575 -> branch_575 (pre-receive hook declined)
! [remote rejected] branch_576 -> branch_576 (pre-receive hook declined)
! [remote rejected] branch_577 -> branch_577 (pre-receive hook declined)
! [remote rejected] branch_578 -> branch_578 (pre-receive hook declined)
! [remote rejected] branch_579 -> branch_579 (pre-receive hook declined)
! [remote rejected] branch_580 -> branch_580 (pre-receive hook declined)
! [remote rejected] branch_581 -> branch_581 (pre-receive hook declined)
! [remote rejected] branch_582 -> branch_582 (pre-receive hook declined)
! [remote rejected] branch_583 -> branch_583 (pre-receive hook declined)
! [remote rejected] branch_584 -> branch_584 (pre-receive hook declined)
! [remote rejected] branch_585 -> branch_585 (pre-receive hook declined)
! [remote rejected] branch_586 -> branch_586 (pre-receive hook declined)
! [remote rejected] branch_587 -> branch_587 (pre-receive hook declined)
! [remote rejected] branch_588 -> branch_588 (pre-receive hook declined)
! [remote rejected] branch_589 -> branch_589 (pre-receive hook declined)
! [remote rejected] branch_590 -> branch_590 (pre-receive hook declined)
! [remote rejected] branch_591 -> branch_591 (pre-receive hook declined)
! [remote rejected] branch_592 -> branch_592 (pre-receive hook declined)
! [remote rejected] branch_593 -> branch_593 (pre-receive hook declined)
! [remote rejected] branch_594 -> branch_594 (pre-receive hook declined)
! [remote rejected] branch_595 -> branch_595 (pre-receive hook declined)
! [remote rejected] branch_596 -> branch_596 (pre-receive hook declined)
! [remote rejected] branch_597 -> branch_597 (pre-receive hook declined)
! [remote rejected] branch_598 -> branch_598 (pre-receive hook declined)
! [remote rejected] branch_599 -> branch_599 (pre-receive hook declined)
! [remote rejected] branch_600 -> branch_600 (pre-receive hook declined)
! [remote rejected] branch_601 -> branch_601 (pre-receive hook declined)
! [remote rejected] branch_602 -> branch_602 (pre-receive hook declined)
! [remote rejected] branch_603 -> branch_603 (pre-receive hook declined)
! [remote rejected] branch_604 -> branch_604 (pre-receive hook declined)
! [remote rejected] branch_605 -> branch_605 (pre-receive hook declined)
! [remote rejected] branch_606 -> branch_606 (pre-receive hook declined)
! [remote rejected] branch_607 -> branch_607 (pre-receive hook declined)
! [remote rejected] branch_608 -> branch_608 (pre-receive hook declined)
! [remote rejected] branch_609 -> branch_609 (pre-receive hook declined)
! [remote rejected] branch_610 -> branch_610 (pre-receive hook declined)
! [remote rejected] branch_611 -> branch_611 (pre-receive hook declined)
! [remote rejected] branch_612 -> branch_612 (pre-receive hook declined)
! [remote rejected] branch_613 -> branch_613 (pre-receive hook declined)
! [remote rejected] branch_614 -> branch_614 (pre-receive hook declined)
! [remote rejected] branch_615 -> branch_615 (pre-receive hook declined)
! [remote rejected] branch_616 -> branch_616 (pre-receive hook declined)
! [remote rejected] branch_617 -> branch_617 (pre-receive hook declined)
! [remote rejected] branch_618 -> branch_618 (pre-receive hook declined)
! [remote rejected] branch_619 -> branch_619 (pre-receive hook declined)
! [remote rejected] branch_620 -> branch_620 (pre-receive hook declined)
! [remote rejected] branch_621 -> branch_621 (pre-receive hook declined)
! [remote rejected] branch_622 -> branch_622 (pre-receive hook declined)
! [remote rejected] branch_623 -> branch_623 (pre-receive hook declined)
! [remote rejected] branch_624 -> branch_624 (pre-receive hook declined)
! [remote rejected] branch_625 -> branch_625 (pre-receive hook declined)
! [remote rejected] branch_626 -> branch_626 (pre-receive hook declined)
! [remote rejected] branch_627 -> branch_627 (pre-receive hook declined)
! [remote rejected] branch_628 -> branch_628 (pre-receive hook declined)
! [remote rejected] branch_629 -> branch_629 (pre-receive hook declined)
! [remote rejected] branch_630 -> branch_630 (pre-receive hook declined)
! [remote rejected] branch_631 -> branch_631 (pre-receive hook declined)
! [remote rejected] branch_632 -> branch_632 (pre-receive hook declined)
! [remote rejected] branch_633 -> branch_633 (pre-receive hook declined)
! [remote rejected] branch_634 -> branch_634 (pre-receive hook declined)
! [remote rejected] branch_635 -> branch_635 (pre-receive hook declined)
! [remote rejected] branch_636 -> branch_636 (pre-receive hook declined)
! [remote rejected] branch_637 -> branch_637 (pre-receive hook declined)
! [remote rejected] branch_638 -> branch_638 (pre-receive hook declined)
! [remote rejected] branch_639 -> branch_639 (pre-receive hook declined)
! [remote rejected] branch_640 -> branch_640 (pre-receive hook declined)
! [remote rejected] branch_641 -> branch_641 (pre-receive hook declined)
! [remote rejected] branch_642 -> branch_642 (pre-receive hook declined)
! [remote rejected] branch_643 -> branch_643 (pre-receive hook declined)
! [remote rejected] branch_644 -> branch_644 (pre-receive hook declined)
! [remote rejected] branch_645 -> branch_645 (pre-receive hook declined)
! [remote rejected] branch_646 -> branch_646 (pre-receive hook declined)
! [remote rejected] branch_647 -> branch_647 (pre-receive hook declined)
! [remote rejected] branch_648 -> branch_648 (pre-receive hook declined)
! [remote rejected] branch_649 -> branch_649 (pre-receive hook declined)
! [remote rejected] branch_650 -> branch_650 (pre-receive hook declined)
! [remote rejected] branch_651 -> branch_651 (pre-receive hook declined)
! [remote rejected] branch_652 -> branch_652 (pre-receive hook declined)
! [remote rejected] branch_653 -> branch_653 (pre-receive hook declined)
! [remote rejected] branch_654 -> branch_654 (pre-receive hook declined)
! [remote rejected] branch_655 -> branch_655 (pre-receive hook declined)
! [remote rejected] branch_656 -> branch_656 (pre-receive hook declined)
! [remote rejected] branch_657 -> branch_657 (pre-receive hook declined)
! [remote rejected] branch_658 -> branch_658 (pre-receive hook declined)
! [remote rejected] branch_659 -> branch_659 (pre-receive hook declined)
! [remote rejected] branch_660 -> branch_660 (pre-receive hook declined)
! [remote rejected] branch_661 -> branch_661 (pre-receive hook declined)
! [remote rejected] branch_662 -> branch_662 (pre-receive hook declined)
! [remote rejected] branch_663 -> branch_663 (pre-receive hook declined)
! [remote rejected] branch_664 -> branch_664 (pre-receive hook declined)
! [remote rejected] branch_665 -> branch_665 (pre-receive hook declined)
! [remote rejected] branch_666 -> branch_666 (pre-receive hook declined)
! [remote rejected] branch_667 -> branch_667 (pre-receive hook declined)
! [remote rejected] branch_668 -> branch_668 (pre-receive hook declined)
! [remote rejected] branch_669 -> branch_669 (pre-receive hook declined)
! [remote rejected] branch_670 -> branch_670 (pre-receive hook declined)
! [remote rejected] branch_671 -> branch_671 (pre-receive hook declined)
! [remote rejected] branch_672 -> branch_672 (pre-receive hook declined)
! [remote rejected] branch_673 -> branch_673 (pre-receive hook declined)
! [remote rejected] branch_674 -> branch_674 (pre-receive hook declined)
! [remote rejected] branch_675 -> branch_675 (pre-receive hook declined)
! [remote rejected] branch_676 -> branch_676 (pre-receive hook declined)
! [remote rejected] branch_677 -> branch_677 (pre-receive hook declined)
! [remote rejected] branch_678 -> branch_678 (pre-receive hook declined)
! [remote rejected] branch_679 -> branch_679 (pre-receive hook declined)
! [remote rejected] branch_680 -> branch_680 (pre-receive hook declined)
! [remote rejected] branch_681 -> branch_681 (pre-receive hook declined)
! [remote rejected] branch_682 -> branch_682 (pre-receive hook declined)
! [remote rejected] branch_683 -> branch_683 (pre-receive hook declined)
! [remote rejected] branch_684 -> branch_684 (pre-receive hook declined)
! [remote rejected] branch_685 -> branch_685 (pre-receive hook declined)
! [remote rejected] branch_686 -> branch_686 (pre-receive hook declined)
! [remote rejected] branch_687 -> branch_687 (pre-receive hook declined)
! [remote rejected] branch_688 -> branch_688 (pre-receive hook declined)
! [remote rejected] branch_689 -> branch_689 (pre-receive hook declined)
! [remote rejected] branch_690 -> branch_690 (pre-receive hook declined)
! [remote rejected] branch_691 -> branch_691 (pre-receive hook declined)
! [remote rejected] branch_692 -> branch_692 (pre-receive hook declined)
! [remote rejected] branch_693 -> branch_693 (pre-receive hook declined)
! [remote rejected] branch_694 -> branch_694 (pre-receive hook declined)
! [remote rejected] branch_695 -> branch_695 (pre-receive hook declined)
! [remote rejected] branch_696 -> branch_696 (pre-receive hook declined)
! [remote rejected] branch_697 -> branch_697 (pre-receive hook declined)
! [remote rejected] branch_698 -> branch_698 (pre-receive hook declined)
! [remote rejected] branch_699 -> branch_699 (pre-receive hook declined)
! [remote rejected] branch_700 -> branch_700 (pre-receive hook declined)
! [remote rejected] branch_701 -> branch_701 (pre-receive hook declined)
! [remote rejected] branch_702 -> branch_702 (pre-receive hook declined)
! [remote rejected] branch_703 -> branch_703 (pre-receive hook declined)
! [remote rejected] branch_704 -> branch_704 (pre-receive hook declined)
! [remote rejected] branch_705 -> branch_705 (pre-receive hook declined)
! [remote rejected] branch_706 -> branch_706 (pre-receive hook declined)
! [remote rejected] branch_707 -> branch_707 (pre-receive hook declined)
! [remote rejected] branch_708 -> branch_708 (pre-receive hook declined)
! [remote rejected] branch_709 -> branch_709 (pre-receive hook declined)
! [remote rejected] branch_710 -> branch_710 (pre-receive hook declined)
! [remote rejected] branch_711 -> branch_711 (pre-receive hook declined)
! [remote rejected] branch_712 -> branch_712 (pre-receive hook declined)
! [remote rejected] branch_713 -> branch_713 (pre-receive hook declined)
! [remote rejected] branch_714 -> branch_714 (pre-receive hook declined)
! [remote rejected] branch_715 -> branch_715 (pre-receive hook declined)
! [remote rejected] branch_716 -> branch_716 (pre-receive hook declined)
! [remote rejected] branch_717 -> branch_717 (pre-receive hook declined)
! [remote rejected] branch_718 -> branch_718 (pre-receive hook declined)
! [remote rejected] branch_719 -> branch_719 (pre-receive hook declined)
! [remote rejected] branch_720 -> branch_720 (pre-receive hook declined)
! [remote rejected] branch_721 -> branch_721 (pre-receive hook declined)
! [remote rejected] branch_722 -> branch_722 (pre-receive hook declined)
! [remote rejected] branch_723 -> branch_723 (pre-receive hook declined)
! [remote rejected] branch_724 -> branch_724 (pre-receive hook declined)
! [remote rejected] branch_725 -> branch_725 (pre-receive hook declined)
! [remote rejected] branch_726 -> branch_726 (pre-receive hook declined)
! [remote rejected] branch_727 -> branch_727 (pre-receive hook declined)
! [remote rejected] branch_728 -> branch_728 (pre-receive hook declined)
! [remote rejected] branch_729 -> branch_729 (pre-receive hook declined)
! [remote rejected] branch_730 -> branch_730 (pre-receive hook declined)
! [remote rejected] branch_731 -> branch_731 (pre-receive hook declined)
! [remote rejected] branch_732 -> branch_732 (pre-receive hook declined)
! [remote rejected] branch_733 -> branch_733 (pre-receive hook declined)
! [remote rejected] branch_734 -> branch_734 (pre-receive hook declined)
! [remote rejected] branch_735 -> branch_735 (pre-receive hook declined)
! [remote rejected] branch_736 -> branch_736 (pre-receive hook declined)
! [remote rejected] branch_737 -> branch_737 (pre-receive hook declined)
! [remote rejected] branch_738 -> branch_738 (pre-receive hook declined)
! [remote rejected] branch_739 -> branch_739 (pre-receive hook declined)
! [remote rejected] branch_740 -> branch_740 (pre-receive hook declined)
! [remote rejected] branch_741 -> branch_741 (pre-receive hook declined)
! [remote rejected] branch_742 -> branch_742 (pre-receive hook declined)
! [remote rejected] branch_743 -> branch_743 (pre-receive hook declined)
! [remote rejected] branch_744 -> branch_744 (pre-receive hook declined)
! [remote rejected] branch_745 -> branch_745 (pre-receive hook declined)
! [remote rejected] branch_746 -> branch_746 (pre-receive hook declined)
! [remote rejected] branch_747 -> branch_747 (pre-receive hook declined)
! [remote rejected] branch_748 -> branch_748 (pre-receive hook declined)
! [remote rejected] branch_749 -> branch_749 (pre-receive hook declined)
! [remote rejected] branch_750 -> branch_750 (pre-receive hook declined)
! [remote rejected] branch_751 -> branch_751 (pre-receive hook declined)
! [remote rejected] branch_752 -> branch_752 (pre-receive hook declined)
! [remote rejected] branch_753 -> branch_753 (pre-receive hook declined)
! [remote rejected] branch_754 -> branch_754 (pre-receive hook declined)
! [remote rejected] branch_755 -> branch_755 (pre-receive hook declined)
! [remote rejected] branch_756 -> branch_756 (pre-receive hook declined)
! [remote rejected] branch_757 -> branch_757 (pre-receive hook declined)
! [remote rejected] branch_758 -> branch_758 (pre-receive hook declined)
! [remote rejected] branch_759 -> branch_759 (pre-receive hook declined)
! [remote rejected] branch_760 -> branch_760 (pre-receive hook declined)
! [remote rejected] branch_761 -> branch_761 (pre-receive hook declined)
! [remote rejected] branch_762 -> branch_762 (pre-receive hook declined)
! [remote rejected] branch_763 -> branch_763 (pre-receive hook declined)
! [remote rejected] branch_764 -> branch_764 (pre-receive hook declined)
! [remote rejected] branch_765 -> branch_765 (pre-receive hook declined)
! [remote rejected] branch_766 -> branch_766 (pre-receive hook declined)
! [remote rejected] branch_767 -> branch_767 (pre-receive hook declined)
! [remote rejected] branch_768 -> branch_768 (pre-receive hook declined)
! [remote rejected] branch_769 -> branch_769 (pre-receive hook declined)
! [remote rejected] branch_770 -> branch_770 (pre-receive hook declined)
! [remote rejected] branch_771 -> branch_771 (pre-receive hook declined)
! [remote rejected] branch_772 -> branch_772 (pre-receive hook declined)
! [remote rejected] branch_773 -> branch_773 (pre-receive hook declined)
! [remote rejected] branch_774 -> branch_774 (pre-receive hook declined)
! [remote rejected] branch_775 -> branch_775 (pre-receive hook declined)
! [remote rejected] branch_776 -> branch_776 (pre-receive hook declined)
! [remote rejected] branch_777 -> branch_777 (pre-receive hook declined)
! [remote rejected] branch_778 -> branch_778 (pre-receive hook declined)
! [remote rejected] branch_779 -> branch_779 (pre-receive hook declined)
! [remote rejected] branch_780 -> branch_780 (pre-receive hook declined)
! [remote rejected] branch_781 -> branch_781 (pre-receive hook declined)
! [remote rejected] branch_782 -> branch_782 (pre-receive hook declined)
! [remote rejected] branch_783 -> branch_783 (pre-receive hook declined)
! [remote rejected] branch_784 -> branch_784 (pre-receive hook declined)
! [remote rejected] branch_785 -> branch_785 (pre-receive hook declined)
! [remote rejected] branch_786 -> branch_786 (pre-receive hook declined)
! [remote rejected] branch_787 -> branch_787 (pre-receive hook declined)
! [remote rejected] branch_788 -> branch_788 (pre-receive hook declined)
! [remote rejected] branch_789 -> branch_789 (pre-receive hook declined)
! [remote rejected] branch_790 -> branch_790 (pre-receive hook declined)
! [remote rejected] branch_791 -> branch_791 (pre-receive hook declined)
! [remote rejected] branch_792 -> branch_792 (pre-receive hook declined)
! [remote rejected] branch_793 -> branch_793 (pre-receive hook declined)
! [remote rejected] branch_794 -> branch_794 (pre-receive hook declined)
! [remote rejected] branch_795 -> branch_795 (pre-receive hook declined)
! [remote rejected] branch_796 -> branch_796 (pre-receive hook declined)
! [remote rejected] branch_797 -> branch_797 (pre-receive hook declined)
! [remote rejected] branch_798 -> branch_798 (pre-receive hook declined)
! [remote rejected] branch_799 -> branch_799 (pre-receive hook declined)
! [remote rejected] branch_800 -> branch_800 (pre-receive hook declined)
! [remote rejected] branch_801 -> branch_801 (pre-receive hook declined)
! [remote rejected] branch_802 -> branch_802 (pre-receive hook declined)
! [remote rejected] branch_803 -> branch_803 (pre-receive hook declined)
! [remote rejected] branch_804 -> branch_804 (pre-receive hook declined)
! [remote rejected] branch_805 -> branch_805 (pre-receive hook declined)
! [remote rejected] branch_806 -> branch_806 (pre-receive hook declined)
! [remote rejected] branch_807 -> branch_807 (pre-receive hook declined)
! [remote rejected] branch_808 -> branch_808 (pre-receive hook declined)
! [remote rejected] branch_809 -> branch_809 (pre-receive hook declined)
! [remote rejected] branch_810 -> branch_810 (pre-receive hook declined)
! [remote rejected] branch_811 -> branch_811 (pre-receive hook declined)
! [remote rejected] branch_812 -> branch_812 (pre-receive hook declined)
! [remote rejected] branch_813 -> branch_813 (pre-receive hook declined)
! [remote rejected] branch_814 -> branch_814 (pre-receive hook declined)
! [remote rejected] branch_815 -> branch_815 (pre-receive hook declined)
! [remote rejected] branch_816 -> branch_816 (pre-receive hook declined)
! [remote rejected] branch_817 -> branch_817 (pre-receive hook declined)
! [remote rejected] branch_818 -> branch_818 (pre-receive hook declined)
! [remote rejected] branch_819 -> branch_819 (pre-receive hook declined)
! [remote rejected] branch_820 -> branch_820 (pre-receive hook declined)
! [remote rejected] branch_821 -> branch_821 (pre-receive hook declined)
! [remote rejected] branch_822 -> branch_822 (pre-receive hook declined)
! [remote rejected] branch_823 -> branch_823 (pre-receive hook declined)
! [remote rejected] branch_824 -> branch_824 (pre-receive hook declined)
! [remote rejected] branch_825 -> branch_825 (pre-receive hook declined)
! [remote rejected] branch_826 -> branch_826 (pre-receive hook declined)
! [remote rejected] branch_827 -> branch_827 (pre-receive hook declined)
! [remote rejected] branch_828 -> branch_828 (pre-receive hook declined)
! [remote rejected] branch_829 -> branch_829 (pre-receive hook declined)
! [remote rejected] branch_830 -> branch_830 (pre-receive hook declined)
! [remote rejected] branch_831 -> branch_831 (pre-receive hook declined)
! [remote rejected] branch_832 -> branch_832 (pre-receive hook declined)
! [remote rejected] branch_833 -> branch_833 (pre-receive hook declined)
! [remote rejected] branch_834 -> branch_834 (pre-receive hook declined)
! [remote rejected] branch_835 -> branch_835 (pre-receive hook declined)
! [remote rejected] branch_836 -> branch_836 (pre-receive hook declined)
! [remote rejected] branch_837 -> branch_837 (pre-receive hook declined)
! [remote rejected] branch_838 -> branch_838 (pre-receive hook declined)
! [remote rejected] branch_839 -> branch_839 (pre-receive hook declined)
! [remote rejected] branch_840 -> branch_840 (pre-receive hook declined)
! [remote rejected] branch_841 -> branch_841 (pre-receive hook declined)
! [remote rejected] branch_842 -> branch_842 (pre-receive hook declined)
! [remote rejected] branch_843 -> branch_843 (pre-receive hook declined)
! [remote rejected] branch_844 -> branch_844 (pre-receive hook declined)
! [remote rejected] branch_845 -> branch_845 (pre-receive hook declined)
! [remote rejected] branch_846 -> branch_846 (pre-receive hook declined)
! [remote rejected] branch_847 -> branch_847 (pre-receive hook declined)
! [remote rejected] branch_848 -> branch_848 (pre-receive hook declined)
! [remote rejected] branch_849 -> branch_849 (pre-receive hook declined)
! [remote rejected] branch_850 -> branch_850 (pre-receive hook declined)
! [remote rejected] branch_851 -> branch_851 (pre-receive hook declined)
! [remote rejected] branch_852 -> branch_852 (pre-receive hook declined)
! [remote rejected] branch_853 -> branch_853 (pre-receive hook declined)
! [remote rejected] branch_854 -> branch_854 (pre-receive hook declined)
! [remote rejected] branch_855 -> branch_855 (pre-receive hook declined)
! [remote rejected] branch_856 -> branch_856 (pre-receive hook declined)
! [remote rejected] branch_857 -> branch_857 (pre-receive hook declined)
! [remote rejected] branch_858 -> branch_858 (pre-receive hook declined)
! [remote rejected] branch_859 -> branch_859 (pre-receive hook declined)
! [remote rejected] branch_860 -> branch_860 (pre-receive hook declined)
! [remote rejected] branch_861 -> branch_861 (pre-receive hook declined)
! [remote rejected] branch_862 -> branch_862 (pre-receive hook declined)
! [remote rejected] branch_863 -> branch_863 (pre-receive hook declined)
! [remote rejected] branch_864 -> branch_864 (pre-receive hook declined)
! [remote rejected] branch_865 -> branch_865 (pre-receive hook declined)
! [remote rejected] branch_866 -> branch_866 (pre-receive hook declined)
! [remote rejected] branch_867 -> branch_867 (pre-receive hook declined)
! [remote rejected] branch_868 -> branch_868 (pre-receive hook declined)
! [remote rejected] branch_869 -> branch_869 (pre-receive hook declined)
! [remote rejected] branch_870 -> branch_870 (pre-receive hook declined)
! [remote rejected] branch_871 -> branch_871 (pre-receive hook declined)
! [remote rejected] branch_872 -> branch_872 (pre-receive hook declined)
! [remote rejected] branch_873 -> branch_873 (pre-receive hook declined)
! [remote rejected] branch_874 -> branch_874 (pre-receive hook declined)
! [remote rejected] branch_875 -> branch_875 (pre-receive hook declined)
! [remote rejected] branch_876 -> branch_876 (pre-receive hook declined)
! [remote rejected] branch_877 -> branch_877 (pre-receive hook declined)
! [remote rejected] branch_878 -> branch_878 (pre-receive hook declined)
! [remote rejected] branch_879 -> branch_879 (pre-receive hook declined)
! [remote rejected] branch_880 -> branch_880 (pre-receive hook declined)
! [remote rejected] branch_881 -> branch_881 (pre-receive hook declined)
! [remote rejected] branch_882 -> branch_882 (pre-receive hook declined)
! [remote rejected] branch_883 -> branch_883 (pre-receive hook declined)
! [remote rejected] branch_884 -> branch_884 (pre-receive hook declined)
! [remote rejected] branch_885 -> branch_885 (pre-receive hook declined)
! [remote rejected] branch_886 -> branch_886 (pre-receive hook declined)
! [remote rejected] branch_887 -> branch_887 (pre-receive hook declined)
! [remote rejected] branch_888 -> branch_888 (pre-receive hook declined)
! [remote rejected] branch_889 -> branch_889 (pre-receive hook declined)
! [remote rejected] branch_890 -> branch_890 (pre-receive hook declined)
! [remote rejected] branch_891 -> branch_891 (pre-receive hook declined)
! [remote rejected] branch_892 -> branch_892 (pre-receive hook declined)
! [remote rejected] branch_893 -> branch_893 (pre-receive hook declined)
! [remote rejected] branch_894 -> branch_894 (pre-receive hook declined)
! [remote rejected] branch_895 -> branch_895 (pre-receive hook declined)
! [remote rejected] branch_896 -> branch_896 (pre-receive hook declined)
! [remote rejected] branch_897 -> branch_897 (pre-receive hook declined)
! [remote rejected] branch_898 -> branch_898 (pre-receive hook declined)
! [remote rejected] branch_899 -> branch_899 (pre-receive hook declined)
! [remote rejected] branch_900 -> branch_900 (pre-receive hook declined)
! [remote rejected] branch_901 -> branch_901 (pre-receive hook declined)
! [remote rejected] branch_902 -> branch_902 (pre-receive hook declined)
! [remote rejected] branch_903 -> branch_903 (pre-receive hook declined)
! [remote rejected] branch_904 -> branch_904 (pre-receive hook declined)
! [remote rejected] branch_905 -> branch_905 (pre-receive hook declined)
! [remote rejected] branch_906 -> branch_906 (pre-receive hook declined)
! [remote rejected] branch_907 -> branch_907 (pre-receive hook declined)
! [remote rejected] branch_908 -> branch_908 (pre-receive hook declined)
! [remote rejected] branch_909 -> branch_909 (pre-receive hook declined)
! [remote rejected] branch_910 -> branch_910 (pre-receive hook declined)
! [remote rejected] branch_911 -> branch_911 (pre-receive hook declined)
! [remote rejected] branch_912 -> branch_912 (pre-receive hook declined)
! [remote rejected] branch_913 -> branch_913 (pre-receive hook declined)
! [remote rejected] branch_914 -> branch_914 (pre-receive hook declined)
! [remote rejected] branch_915 -> branch_915 (pre-receive hook declined)
! [remote rejected] branch_916 -> branch_916 (pre-receive hook declined)
! [remote rejected] branch_917 -> branch_917 (pre-receive hook declined)
! [remote rejected] branch_918 -> branch_918 (pre-receive hook declined)
! [remote rejected] branch_919 -> branch_919 (pre-receive hook declined)
! [remote rejected] branch_920 -> branch_920 (pre-receive hook declined)
! [remote rejected] branch_921 -> branch_921 (pre-receive hook declined)
! [remote rejected] branch_922 -> branch_922 (pre-receive hook declined)
! [remote rejected] branch_923 -> branch_923 (pre-receive hook declined)
! [remote rejected] branch_924 -> branch_924 (pre-receive hook declined)
! [remote rejected] branch_925 -> branch_925 (pre-receive hook declined)
! [remote rejected] branch_926 -> branch_926 (pre-receive hook declined)
! [remote rejected] branch_927 -> branch_927 (pre-receive hook declined)
! [remote rejected] branch_928 -> branch_928 (pre-receive hook declined)
! [remote rejected] branch_929 -> branch_929 (pre-receive hook declined)
! [remote rejected] branch_930 -> branch_930 (pre-receive hook declined)
! [remote rejected] branch_931 -> branch_931 (pre-receive hook declined)
! [remote rejected] branch_932 -> branch_932 (pre-receive hook declined)
! [remote rejected] branch_933 -> branch_933 (pre-receive hook declined)
! [remote rejected] branch_934 -> branch_934 (pre-receive hook declined)
! [remote rejected] branch_935 -> branch_935 (pre-receive hook declined)
! [remote rejected] branch_936 -> branch_936 (pre-receive hook declined)
! [remote rejected] branch_937 -> branch_937 (pre-receive hook declined)
! [remote rejected] branch_938 -> branch_938 (pre-receive hook declined)
! [remote rejected] branch_939 -> branch_939 (pre-receive hook declined)
! [remote rejected] branch_940 -> branch_940 (pre-receive hook declined)
! [remote rejected] branch_941 -> branch_941 (pre-receive hook declined)
! [remote rejected] branch_942 -> branch_942 (pre-receive hook declined)
! [remote rejected] branch_943 -> branch_943 (pre-receive hook declined)
! [remote rejected] branch_944 -> branch_944 (pre-receive hook declined)
! [remote rejected] branch_945 -> branch_945 (pre-receive hook declined)
! [remote rejected] branch_946 -> branch_946 (pre-receive hook declined)
! [remote rejected] branch_947 -> branch_947 (pre-receive hook declined)
! [remote rejected] branch_948 -> branch_948 (pre-receive hook declined)
! [remote rejected] branch_949 -> branch_949 (pre-receive hook declined)
! [remote rejected] branch_950 -> branch_950 (pre-receive hook declined)
! [remote rejected] branch_951 -> branch_951 (pre-receive hook declined)
! [remote rejected] branch_952 -> branch_952 (pre-receive hook declined)
! [remote rejected] branch_953 -> branch_953 (pre-receive hook declined)
! [remote rejected] branch_954 -> branch_954 (pre-receive hook declined)
! [remote rejected] branch_955 -> branch_955 (pre-receive hook declined)
! [remote rejected] branch_956 -> branch_956 (pre-receive hook declined)
! [remote rejected] branch_957 -> branch_957 (pre-receive hook declined)
! [remote rejected] branch_958 -> branch_958 (pre-receive hook declined)
! [remote rejected] branch_959 -> branch_959 (pre-receive hook declined)
! [remote rejected] branch_960 -> branch_960 (pre-receive hook declined)
! [remote rejected] branch_961 -> branch_961 (pre-receive hook declined)
! [remote rejected] branch_962 -> branch_962 (pre-receive hook declined)
! [remote rejected] branch_963 -> branch_963 (pre-receive hook declined)
! [remote rejected] branch_964 -> branch_964 (pre-receive hook declined)
! [remote rejected] branch_965 -> branch_965 (pre-receive hook declined)
! [remote rejected] branch_966 -> branch_966 (pre-receive hook declined)
! [remote rejected] branch_967 -> branch_967 (pre-receive hook declined)
! [remote rejected] branch_968 -> branch_968 (pre-receive hook declined)
! [remote rejected] branch_969 -> branch_969 (pre-receive hook declined)
! [remote rejected] branch_970 -> branch_970 (pre-receive hook declined)
! [remote rejected] branch_971 -> branch_971 (pre-receive hook declined)
! [remote rejected] branch_972 -> branch_972 (pre-receive hook declined)
! [remote rejected] branch_973 -> branch_973 (pre-receive hook declined)
! [remote rejected] branch_974 -> branch_974 (pre-receive hook declined)
! [remote rejected] branch_975 -> branch_975 (pre-receive hook declined)
! [remote rejected] branch_976 -> branch_976 (pre-receive hook declined)
! [remote rejected] branch_977 -> branch_977 (pre-receive hook declined)
! [remote rejected] branch_978 -> branch_978 (pre-receive hook declined)
! [remote rejected] branch_979 -> branch_979 (pre-receive hook declined)
! [remote rejected] branch_980 -> branch_980 (pre-receive hook declined)
! [remote rejected] branch_981 -> branch_981 (pre-receive hook declined)
! [remote rejected] branch_982 -> branch_982 (pre-receive hook declined)
! [remote rejected] branch_983 -> branch_983 (pre-receive hook declined)
! [remote rejected] branch_984 -> branch_984 (pre-receive hook declined)
! [remote rejected] branch_985 -> branch_985 (pre-receive hook declined)
! [remote rejected] branch_986 -> branch_986 (pre-receive hook declined)
! [remote rejected] branch_987 -> branch_987 (pre-receive hook declined)
! [remote rejected] branch_988 -> branch_988 (pre-receive hook declined)
! [remote rejected] branch_989 -> branch_989 (pre-receive hook declined)
! [remote rejected] branch_990 -> branch_990 (pre-receive hook declined)
! [remote rejected] branch_991 -> branch_991 (pre-receive hook declined)
! [remote rejected] branch_992 -> branch_992 (pre-receive hook declined)
! [remote rejected] branch_993 -> branch_993 (pre-receive hook declined)
! [remote rejected] branch_994 -> branch_994 (pre-receive hook declined)
! [remote rejected] branch_995 -> branch_995 (pre-receive hook declined)
! [remote rejected] branch_996 -> branch_996 (pre-receive hook declined)
! [remote rejected] branch_997 -> branch_997 (pre-receive hook declined)
! [remote rejected] branch_998 -> branch_998 (pre-receive hook declined)
! [remote rejected] branch_999 -> branch_999 (pre-receive hook declined)
error: failed to push some refs to './victim.git'
not ok 13 - pre-receive hook that forgets to
--
Brief whoami: NonStop&UNIX developer since approximately
UNIX(421664400)
NonStop(211288444200000000)
-- In real life, I talk too much.
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-07 23:37 Help needed on 2.54.0-rc0 t5301.13 looping rsbecker @ 2026-04-08 5:20 ` Jeff King 2026-04-08 5:43 ` Jeff King 2026-04-08 15:50 ` Help needed on 2.54.0-rc0 t5301.13 looping Junio C Hamano 0 siblings, 2 replies; 18+ messages in thread From: Jeff King @ 2026-04-08 5:20 UTC (permalink / raw) To: rsbecker; +Cc: Junio C Hamano, Adrian Ratiu, git On Tue, Apr 07, 2026 at 07:37:49PM -0400, rsbecker@nexbridge.com wrote: > Weird fail on t5401.13. Any opinions or advise on this? > > expecting success of 5401.13 'pre-receive hook that forgets to read its > input': > test_hook --clobber -C victim.git pre-receive <<-\EOF && > exit 0 > EOF > rm -f victim.git/hooks/update victim.git/hooks/post-update && > > test_seq -f "create refs/heads/branch_%d main" 100 999 | > git update-ref --stdin && > git push ./victim.git "+refs/heads/*:refs/heads/*" OK, so this test is trying to feed a bunch of data to a pre-receive hook that doesn't read anything, and we want to make sure we aren't killed by SIGPIPE. When the test was added originally in ec7dbd145b (receive-pack: allow hooks to ignore its standard input stream, 2014-09-12), we just stuck a: sigchain_push(SIGPIPE, SIG_IGN); at the top of the hook function. But now that function has been rewritten to use the hook API, and that sigchain_push() is gone. What does the new hook API do? It works with run-command's run_processes_parallel() function. Which similarly ignores SIGPIPE, courtesy of ec0becacc9 (run-command: add stdin callback for parallelization, 2026-01-28): /* * Child tasks might receive input via stdin, terminating early (or not), so * ignore the default SIGPIPE which gets handled by each feed_pipe_fn which * actually writes the data to children stdin fds. */ sigchain_push(SIGPIPE, SIG_IGN); OK, so far so good. But that's not quite the end of the story. In pp_init(), we then sigchain_push() another handler, but this time it's a real function: static void handle_children_on_signal(int signo) { kill_children_signal(pp_for_signal, signo); sigchain_pop(signo); raise(signo); } So now when we get a SIGPIPE, we end up there. It tries to propagate the signal to any child processes we spawned. Which is a bit funny, since it was the child process closing that caused us to get the signal in the first place, but of course our handler doesn't know that. And then afterwards, it pops itself off the handler stack and re-raises. But that will hit the SIG_IGN we pushed earlier and do nothing. So that part isn't interesting. What is interesting is that we end up calling "kill(<pid>, SIGPIPE)" on the child via kill_children_signal(). At least on my Linux system that works fine, since we haven't reaped the process via wait() yet. But of course nothing interesting happens to the child, which has already exited. Killing it with SIGPIPE does not seem to affect its exit code. However, I could believe that on some other system it might behave differently. Possibly even racily. For example, if the child process had closed its pipe (giving us SIGPIPE in the parent) but not yet fully exited, could our kill() cause it to change its exit code? And then it would look like the hook reported failure (because it died by signal). And I'd expect the output you saw. I think the root of the issue is that we should not be trying to propagate SIGPIPE to the child in this case at all. Our handler is pushed there only because it's part of sigchain_push_common(), which is sensible: in general if we are dying to SIGPIPE we want to do our cleanup. It's just funny in this case with the ordering of our SIG_IGN, because now that SIG_IGN isn't on top of the stack anymore. I.e., I think we want to reorder like this: diff --git a/run-command.c b/run-command.c index 32c290ee6a..8a95f7ff1e 100644 --- a/run-command.c +++ b/run-command.c @@ -1895,14 +1895,19 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) "max:%"PRIuMAX, (uintmax_t)opts->processes); + pp_init(&pp, opts, &pp_sig); + /* * Child tasks might receive input via stdin, terminating early (or not), so * ignore the default SIGPIPE which gets handled by each feed_pipe_fn which * actually writes the data to children stdin fds. + * + * This _must_ come after pp_init(), because it installs its own + * SIGPIPE handler (to cleanup children), and we want to supersede + * that. */ sigchain_push(SIGPIPE, SIG_IGN); - pp_init(&pp, opts, &pp_sig); while (1) { for (i = 0; i < spawn_cap && !pp.shutdown && Does that make your problem go away? I suspect we could construct a related case that does fail on Linux without the patch above. Imagine we actually have two hooks running in parallel. The first one is fast and does not read its input, and the second one is slow. We'll get SIGPIPE writing to the first one, and then kill _both_ children. But that's wrong! There is no reason to kill the second hook, as our intent was to ignore SIGPIPE. -Peff ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 5:20 ` Jeff King @ 2026-04-08 5:43 ` Jeff King 2026-04-08 11:53 ` Adrian Ratiu 2026-04-08 15:50 ` Help needed on 2.54.0-rc0 t5301.13 looping Junio C Hamano 1 sibling, 1 reply; 18+ messages in thread From: Jeff King @ 2026-04-08 5:43 UTC (permalink / raw) To: rsbecker; +Cc: Junio C Hamano, Adrian Ratiu, git On Wed, Apr 08, 2026 at 01:20:31AM -0400, Jeff King wrote: > I suspect we could construct a related case that does fail on Linux > without the patch above. Imagine we actually have two hooks running in > parallel. The first one is fast and does not read its input, and the > second one is slow. We'll get SIGPIPE writing to the first one, and then > kill _both_ children. But that's wrong! There is no reason to kill the > second hook, as our intent was to ignore SIGPIPE. This would require running hooks in parallel, which isn't implemented yet for v2.54.0. But if I build on top of the ar/parallel-hooks topic, then this test: diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 44ec875aef..97257763d3 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -139,4 +139,43 @@ test_expect_success 'pre-receive hook that forgets to read its input' ' git push ./victim.git "+refs/heads/*:refs/heads/*" ' +test_expect_success 'hooks in parallel that do not read input' ' + # Add this to our $PATH to avoid having to write the whole trash + # directory into our config options, which would require quoting. + mkdir bin && + PATH=$PWD/bin:$PATH && + + write_script bin/hook-fast <<-\EOF && + # This hook does not read its input, so the parent process + # may see SIGPIPE if it is not ignored. It should happen + # relatively quickly. + exit 0 + EOF + + write_script bin/hook-slow <<-\EOF && + # This hook is slow, so we expect it to still be running + # when the other hook has exited (and the parent has a pipe error + # writing to it). + # + # So we want to be slow enough that we expect this to happen, but not + # so slow that the test takes forever. 1 second is probably enough + # in practice (and if it is occasionally not on a loaded system, we + # will err on the side of having the test pass). + sleep 1 + exit 0 + EOF + + + git init --bare parallel.git && + git -C parallel.git config hook.fast.command "hook-fast" && + git -C parallel.git config hook.fast.event pre-receive && + git -C parallel.git config hook.fast.parallel true && + git -C parallel.git config hook.slow.command "hook-slow" && + git -C parallel.git config hook.slow.event pre-receive && + git -C parallel.git config hook.slow.parallel true && + git -C parallel.git config hook.jobs 2 && + + git push ./parallel.git "+refs/heads/*:refs/heads/*" +' + test_done fails reliably. And applying the patch I suggested earlier fixes it. So I think it's probably a good idea regardless, though I'm still curious to see if it solves Randall's non-parallel case on NonStop. -Peff ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 5:43 ` Jeff King @ 2026-04-08 11:53 ` Adrian Ratiu 2026-04-08 15:44 ` rsbecker ` (3 more replies) 0 siblings, 4 replies; 18+ messages in thread From: Adrian Ratiu @ 2026-04-08 11:53 UTC (permalink / raw) To: Jeff King, rsbecker; +Cc: Junio C Hamano, git On Wed, 08 Apr 2026, Jeff King <peff@peff.net> wrote: > On Wed, Apr 08, 2026 at 01:20:31AM -0400, Jeff King wrote: > >> I suspect we could construct a related case that does fail on Linux >> without the patch above. Imagine we actually have two hooks running in >> parallel. The first one is fast and does not read its input, and the >> second one is slow. We'll get SIGPIPE writing to the first one, and then >> kill _both_ children. But that's wrong! There is no reason to kill the >> second hook, as our intent was to ignore SIGPIPE. > > This would require running hooks in parallel, which isn't implemented > yet for v2.54.0. But if I build on top of the ar/parallel-hooks topic, > then this test: > > diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh > index 44ec875aef..97257763d3 100755 > --- a/t/t5401-update-hooks.sh > +++ b/t/t5401-update-hooks.sh > @@ -139,4 +139,43 @@ test_expect_success 'pre-receive hook that forgets to read its input' ' > git push ./victim.git "+refs/heads/*:refs/heads/*" > ' > > +test_expect_success 'hooks in parallel that do not read input' ' > + # Add this to our $PATH to avoid having to write the whole trash > + # directory into our config options, which would require quoting. > + mkdir bin && > + PATH=$PWD/bin:$PATH && > + > + write_script bin/hook-fast <<-\EOF && > + # This hook does not read its input, so the parent process > + # may see SIGPIPE if it is not ignored. It should happen > + # relatively quickly. > + exit 0 > + EOF > + > + write_script bin/hook-slow <<-\EOF && > + # This hook is slow, so we expect it to still be running > + # when the other hook has exited (and the parent has a pipe error > + # writing to it). > + # > + # So we want to be slow enough that we expect this to happen, but not > + # so slow that the test takes forever. 1 second is probably enough > + # in practice (and if it is occasionally not on a loaded system, we > + # will err on the side of having the test pass). > + sleep 1 > + exit 0 > + EOF > + > + > + git init --bare parallel.git && > + git -C parallel.git config hook.fast.command "hook-fast" && > + git -C parallel.git config hook.fast.event pre-receive && > + git -C parallel.git config hook.fast.parallel true && > + git -C parallel.git config hook.slow.command "hook-slow" && > + git -C parallel.git config hook.slow.event pre-receive && > + git -C parallel.git config hook.slow.parallel true && > + git -C parallel.git config hook.jobs 2 && > + > + git push ./parallel.git "+refs/heads/*:refs/heads/*" > +' > + > test_done > > fails reliably. And applying the patch I suggested earlier fixes it. > > So I think it's probably a good idea regardless, though I'm still > curious to see if it solves Randall's non-parallel case on NonStop. Thanks Peff for the in-depth analysis, fix and test. It is very much appreciated. I missed this case. I agree with your assesement: this must be fixed regardless if it also fixes Randall's case or not (might be a separate root cause). I would proceed like this (obviously crediting you for the fix & test): If it fixes Randall's case: send a standalone bug-fix patch, then integrate the test into the parallel series. else integrate both the fix and the test into the parallel series. @Randall please let us know if the fix proposed by Peff in the other response works for you. ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 11:53 ` Adrian Ratiu @ 2026-04-08 15:44 ` rsbecker 2026-04-08 15:52 ` rsbecker ` (2 subsequent siblings) 3 siblings, 0 replies; 18+ messages in thread From: rsbecker @ 2026-04-08 15:44 UTC (permalink / raw) To: 'Adrian Ratiu', 'Jeff King'; +Cc: 'Junio C Hamano', git On April 8, 2026 7:53 AM, Adrian Ratiu wrote: >On Wed, 08 Apr 2026, Jeff King <peff@peff.net> wrote: >> On Wed, Apr 08, 2026 at 01:20:31AM -0400, Jeff King wrote: >> >>> I suspect we could construct a related case that does fail on Linux >>> without the patch above. Imagine we actually have two hooks running in >>> parallel. The first one is fast and does not read its input, and the >>> second one is slow. We'll get SIGPIPE writing to the first one, and then >>> kill _both_ children. But that's wrong! There is no reason to kill the >>> second hook, as our intent was to ignore SIGPIPE. >> >> This would require running hooks in parallel, which isn't implemented >> yet for v2.54.0. But if I build on top of the ar/parallel-hooks topic, >> then this test: >> >> diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh >> index 44ec875aef..97257763d3 100755 >> --- a/t/t5401-update-hooks.sh >> +++ b/t/t5401-update-hooks.sh >> @@ -139,4 +139,43 @@ test_expect_success 'pre-receive hook that forgets to >read its input' ' >> git push ./victim.git "+refs/heads/*:refs/heads/*" >> ' >> >> +test_expect_success 'hooks in parallel that do not read input' ' >> + # Add this to our $PATH to avoid having to write the whole trash >> + # directory into our config options, which would require quoting. >> + mkdir bin && >> + PATH=$PWD/bin:$PATH && >> + >> + write_script bin/hook-fast <<-\EOF && >> + # This hook does not read its input, so the parent process >> + # may see SIGPIPE if it is not ignored. It should happen >> + # relatively quickly. >> + exit 0 >> + EOF >> + >> + write_script bin/hook-slow <<-\EOF && >> + # This hook is slow, so we expect it to still be running >> + # when the other hook has exited (and the parent has a pipe error >> + # writing to it). >> + # >> + # So we want to be slow enough that we expect this to happen, but not >> + # so slow that the test takes forever. 1 second is probably enough >> + # in practice (and if it is occasionally not on a loaded system, we >> + # will err on the side of having the test pass). >> + sleep 1 >> + exit 0 >> + EOF >> + >> + >> + git init --bare parallel.git && >> + git -C parallel.git config hook.fast.command "hook-fast" && >> + git -C parallel.git config hook.fast.event pre-receive && >> + git -C parallel.git config hook.fast.parallel true && >> + git -C parallel.git config hook.slow.command "hook-slow" && >> + git -C parallel.git config hook.slow.event pre-receive && >> + git -C parallel.git config hook.slow.parallel true && >> + git -C parallel.git config hook.jobs 2 && >> + >> + git push ./parallel.git "+refs/heads/*:refs/heads/*" >> +' >> + >> test_done >> >> fails reliably. And applying the patch I suggested earlier fixes it. >> >> So I think it's probably a good idea regardless, though I'm still >> curious to see if it solves Randall's non-parallel case on NonStop. > >Thanks Peff for the in-depth analysis, fix and test. >It is very much appreciated. I missed this case. > >I agree with your assesement: this must be fixed regardless if it also >fixes Randall's case or not (might be a separate root cause). > >I would proceed like this (obviously crediting you for the fix & test): > >If it fixes Randall's case: > send a standalone bug-fix patch, then integrate the test into the > parallel series. >else > integrate both the fix and the test into the parallel series. > >@Randall please let us know if the fix proposed by Peff in the other >response works for you. Yes, this fix worked on NonStop. Thanks Peff. The new test also passed. ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 11:53 ` Adrian Ratiu 2026-04-08 15:44 ` rsbecker @ 2026-04-08 15:52 ` rsbecker 2026-04-08 15:55 ` rsbecker 2026-04-08 16:53 ` Junio C Hamano 3 siblings, 0 replies; 18+ messages in thread From: rsbecker @ 2026-04-08 15:52 UTC (permalink / raw) To: 'Adrian Ratiu', 'Jeff King'; +Cc: 'Junio C Hamano', git On April 8, 2026 7:53 AM, Adrian Ratiu wrote: >To: Jeff King <peff@peff.net>; rsbecker@nexbridge.com >Cc: Junio C Hamano <gitster@pobox.com>; git@vger.kernel.org >Subject: Re: Help needed on 2.54.0-rc0 t5301.13 looping. > >On Wed, 08 Apr 2026, Jeff King <peff@peff.net> wrote: >> On Wed, Apr 08, 2026 at 01:20:31AM -0400, Jeff King wrote: >> >>> I suspect we could construct a related case that does fail on Linux >>> without the patch above. Imagine we actually have two hooks running in >>> parallel. The first one is fast and does not read its input, and the >>> second one is slow. We'll get SIGPIPE writing to the first one, and then >>> kill _both_ children. But that's wrong! There is no reason to kill the >>> second hook, as our intent was to ignore SIGPIPE. >> >> This would require running hooks in parallel, which isn't implemented >> yet for v2.54.0. But if I build on top of the ar/parallel-hooks topic, >> then this test: >> >> diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh >> index 44ec875aef..97257763d3 100755 >> --- a/t/t5401-update-hooks.sh >> +++ b/t/t5401-update-hooks.sh >> @@ -139,4 +139,43 @@ test_expect_success 'pre-receive hook that forgets to >read its input' ' >> git push ./victim.git "+refs/heads/*:refs/heads/*" >> ' >> >> +test_expect_success 'hooks in parallel that do not read input' ' >> + # Add this to our $PATH to avoid having to write the whole trash >> + # directory into our config options, which would require quoting. >> + mkdir bin && >> + PATH=$PWD/bin:$PATH && >> + >> + write_script bin/hook-fast <<-\EOF && >> + # This hook does not read its input, so the parent process >> + # may see SIGPIPE if it is not ignored. It should happen >> + # relatively quickly. >> + exit 0 >> + EOF >> + >> + write_script bin/hook-slow <<-\EOF && >> + # This hook is slow, so we expect it to still be running >> + # when the other hook has exited (and the parent has a pipe error >> + # writing to it). >> + # >> + # So we want to be slow enough that we expect this to happen, but not >> + # so slow that the test takes forever. 1 second is probably enough >> + # in practice (and if it is occasionally not on a loaded system, we >> + # will err on the side of having the test pass). >> + sleep 1 >> + exit 0 >> + EOF >> + >> + >> + git init --bare parallel.git && >> + git -C parallel.git config hook.fast.command "hook-fast" && >> + git -C parallel.git config hook.fast.event pre-receive && >> + git -C parallel.git config hook.fast.parallel true && >> + git -C parallel.git config hook.slow.command "hook-slow" && >> + git -C parallel.git config hook.slow.event pre-receive && >> + git -C parallel.git config hook.slow.parallel true && >> + git -C parallel.git config hook.jobs 2 && >> + >> + git push ./parallel.git "+refs/heads/*:refs/heads/*" >> +' >> + >> test_done >> >> fails reliably. And applying the patch I suggested earlier fixes it. >> >> So I think it's probably a good idea regardless, though I'm still >> curious to see if it solves Randall's non-parallel case on NonStop. > >Thanks Peff for the in-depth analysis, fix and test. >It is very much appreciated. I missed this case. > >I agree with your assesement: this must be fixed regardless if it also >fixes Randall's case or not (might be a separate root cause). > >I would proceed like this (obviously crediting you for the fix & test): > >If it fixes Randall's case: > send a standalone bug-fix patch, then integrate the test into the > parallel series. >else > integrate both the fix and the test into the parallel series. > >@Randall please let us know if the fix proposed by Peff in the other >response works for you. This fix, however, causes an unreported infinite loop in t5571: expecting success of 5571.11 'sigpipe does not cause pre-push hook failure': test_hook --clobber pre-push <<-\EOF && exit 0 EOF git push parent1 "refs/heads/b/*:refs/heads/b/*" Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) <and hung> ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 11:53 ` Adrian Ratiu 2026-04-08 15:44 ` rsbecker 2026-04-08 15:52 ` rsbecker @ 2026-04-08 15:55 ` rsbecker 2026-04-08 16:53 ` Junio C Hamano 3 siblings, 0 replies; 18+ messages in thread From: rsbecker @ 2026-04-08 15:55 UTC (permalink / raw) To: 'Adrian Ratiu', 'Jeff King'; +Cc: 'Junio C Hamano', git On April 8, 2026 11:53 AM, I wrote (accidentally): >To: 'Adrian Ratiu' <adrian.ratiu@collabora.com>; 'Jeff King' <peff@peff.net> >Cc: 'Junio C Hamano' <gitster@pobox.com>; 'git@vger.kernel.org' ><git@vger.kernel.org> >Subject: RE: Help needed on 2.54.0-rc0 t5301.13 looping. > >On April 8, 2026 7:53 AM, Adrian Ratiu wrote: >>To: Jeff King <peff@peff.net>; rsbecker@nexbridge.com >>Cc: Junio C Hamano <gitster@pobox.com>; git@vger.kernel.org >>Subject: Re: Help needed on 2.54.0-rc0 t5301.13 looping. >> >>On Wed, 08 Apr 2026, Jeff King <peff@peff.net> wrote: >>> On Wed, Apr 08, 2026 at 01:20:31AM -0400, Jeff King wrote: >>> >>>> I suspect we could construct a related case that does fail on Linux >>>> without the patch above. Imagine we actually have two hooks running >>>> in parallel. The first one is fast and does not read its input, and >>>> the second one is slow. We'll get SIGPIPE writing to the first one, >>>> and then kill _both_ children. But that's wrong! There is no reason >>>> to kill the second hook, as our intent was to ignore SIGPIPE. >>> >>> This would require running hooks in parallel, which isn't implemented >>> yet for v2.54.0. But if I build on top of the ar/parallel-hooks >>> topic, then this test: >>> >>> diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index >>> 44ec875aef..97257763d3 100755 >>> --- a/t/t5401-update-hooks.sh >>> +++ b/t/t5401-update-hooks.sh >>> @@ -139,4 +139,43 @@ test_expect_success 'pre-receive hook that >>> forgets to >>read its input' ' >>> git push ./victim.git "+refs/heads/*:refs/heads/*" >>> ' >>> >>> +test_expect_success 'hooks in parallel that do not read input' ' >>> + # Add this to our $PATH to avoid having to write the whole trash >>> + # directory into our config options, which would require quoting. >>> + mkdir bin && >>> + PATH=$PWD/bin:$PATH && >>> + >>> + write_script bin/hook-fast <<-\EOF && >>> + # This hook does not read its input, so the parent process >>> + # may see SIGPIPE if it is not ignored. It should happen >>> + # relatively quickly. >>> + exit 0 >>> + EOF >>> + >>> + write_script bin/hook-slow <<-\EOF && >>> + # This hook is slow, so we expect it to still be running >>> + # when the other hook has exited (and the parent has a pipe error >>> + # writing to it). >>> + # >>> + # So we want to be slow enough that we expect this to happen, but not >>> + # so slow that the test takes forever. 1 second is probably enough >>> + # in practice (and if it is occasionally not on a loaded system, we >>> + # will err on the side of having the test pass). >>> + sleep 1 >>> + exit 0 >>> + EOF >>> + >>> + >>> + git init --bare parallel.git && >>> + git -C parallel.git config hook.fast.command "hook-fast" && >>> + git -C parallel.git config hook.fast.event pre-receive && >>> + git -C parallel.git config hook.fast.parallel true && >>> + git -C parallel.git config hook.slow.command "hook-slow" && >>> + git -C parallel.git config hook.slow.event pre-receive && >>> + git -C parallel.git config hook.slow.parallel true && >>> + git -C parallel.git config hook.jobs 2 && >>> + >>> + git push ./parallel.git "+refs/heads/*:refs/heads/*" >>> +' >>> + >>> test_done >>> >>> fails reliably. And applying the patch I suggested earlier fixes it. >>> >>> So I think it's probably a good idea regardless, though I'm still >>> curious to see if it solves Randall's non-parallel case on NonStop. >> >>Thanks Peff for the in-depth analysis, fix and test. >>It is very much appreciated. I missed this case. >> >>I agree with your assesement: this must be fixed regardless if it also >>fixes Randall's case or not (might be a separate root cause). >> >>I would proceed like this (obviously crediting you for the fix & test): >> >>If it fixes Randall's case: >> send a standalone bug-fix patch, then integrate the test into the >> parallel series. >>else >> integrate both the fix and the test into the parallel series. >> >>@Randall please let us know if the fix proposed by Peff in the other >>response works for you. > >This fix, however, causes an unreported infinite loop in t5571: > >expecting success of 5571.11 'sigpipe does not cause pre-push hook failure': > test_hook --clobber pre-push <<-\EOF && > exit 0 > EOF > git push parent1 "refs/heads/b/*:refs/heads/b/*" > >Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0) <and hung> I was not patient enough. This continued eventually and passed. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 11:53 ` Adrian Ratiu ` (2 preceding siblings ...) 2026-04-08 15:55 ` rsbecker @ 2026-04-08 16:53 ` Junio C Hamano 2026-04-08 16:58 ` rsbecker 2026-04-08 17:01 ` Adrian Ratiu 3 siblings, 2 replies; 18+ messages in thread From: Junio C Hamano @ 2026-04-08 16:53 UTC (permalink / raw) To: Adrian Ratiu; +Cc: Jeff King, rsbecker, git Adrian Ratiu <adrian.ratiu@collabora.com> writes: > Thanks Peff for the in-depth analysis, fix and test. > It is very much appreciated. I missed this case. > > I agree with your assesement: this must be fixed regardless if it also > fixes Randall's case or not (might be a separate root cause). > > I would proceed like this (obviously crediting you for the fix & test): > > If it fixes Randall's case: > send a standalone bug-fix patch, then integrate the test into the > parallel series. > else > integrate both the fix and the test into the parallel series. > > @Randall please let us know if the fix proposed by Peff in the other > response works for you. It sounds sensible, but a standalone fix early before 2.54 final, as the problem and the fix shown by Peff here looked correct, without waiting for NonStop may be simpler to work with. Then, rebuild parallel series on top of the 'master' that has the fix applied, perhaps? Thanks. ^ permalink raw reply [flat|nested] 18+ messages in thread
* RE: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 16:53 ` Junio C Hamano @ 2026-04-08 16:58 ` rsbecker 2026-04-08 17:01 ` Adrian Ratiu 1 sibling, 0 replies; 18+ messages in thread From: rsbecker @ 2026-04-08 16:58 UTC (permalink / raw) To: 'Junio C Hamano', 'Adrian Ratiu'; +Cc: 'Jeff King', git On April 8, 2026 12:54 PM, Junio C Hamano wrote: >Adrian Ratiu <adrian.ratiu@collabora.com> writes: > >> Thanks Peff for the in-depth analysis, fix and test. >> It is very much appreciated. I missed this case. >> >> I agree with your assesement: this must be fixed regardless if it also >> fixes Randall's case or not (might be a separate root cause). >> >> I would proceed like this (obviously crediting you for the fix & test): >> >> If it fixes Randall's case: >> send a standalone bug-fix patch, then integrate the test into the >> parallel series. >> else >> integrate both the fix and the test into the parallel series. >> >> @Randall please let us know if the fix proposed by Peff in the other >> response works for you. > >It sounds sensible, but a standalone fix early before 2.54 final, as the problem and >the fix shown by Peff here looked correct, without waiting for NonStop may be >simpler to work with. Then, rebuild parallel series on top of the 'master' that has >the fix applied, perhaps? The fix works on NonStop as previously supplied. So I'm good. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 16:53 ` Junio C Hamano 2026-04-08 16:58 ` rsbecker @ 2026-04-08 17:01 ` Adrian Ratiu 2026-04-08 17:30 ` [PATCH] t5401: test SIGPIPE with parallel hooks Jeff King 1 sibling, 1 reply; 18+ messages in thread From: Adrian Ratiu @ 2026-04-08 17:01 UTC (permalink / raw) To: Junio C Hamano; +Cc: Jeff King, rsbecker, git On Wed, 08 Apr 2026, Junio C Hamano <gitster@pobox.com> wrote: > Adrian Ratiu <adrian.ratiu@collabora.com> writes: > >> Thanks Peff for the in-depth analysis, fix and test. >> It is very much appreciated. I missed this case. >> >> I agree with your assesement: this must be fixed regardless if it also >> fixes Randall's case or not (might be a separate root cause). >> >> I would proceed like this (obviously crediting you for the fix & test): >> >> If it fixes Randall's case: >> send a standalone bug-fix patch, then integrate the test into the >> parallel series. >> else >> integrate both the fix and the test into the parallel series. >> >> @Randall please let us know if the fix proposed by Peff in the other >> response works for you. > > It sounds sensible, but a standalone fix early before 2.54 final, as > the problem and the fix shown by Peff here looked correct, without > waiting for NonStop may be simpler to work with. Then, rebuild > parallel series on top of the 'master' that has the fix applied, > perhaps? Yes, that is the path forward now that Randall also confirmed the fix works on NonStop (btw thank you Randall). :) Just waiting for Peff to tell me if he wants to send it himself. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] t5401: test SIGPIPE with parallel hooks 2026-04-08 17:01 ` Adrian Ratiu @ 2026-04-08 17:30 ` Jeff King 0 siblings, 0 replies; 18+ messages in thread From: Jeff King @ 2026-04-08 17:30 UTC (permalink / raw) To: Adrian Ratiu; +Cc: Junio C Hamano, rsbecker, git On Wed, Apr 08, 2026 at 08:01:25PM +0300, Adrian Ratiu wrote: > > It sounds sensible, but a standalone fix early before 2.54 final, as > > the problem and the fix shown by Peff here looked correct, without > > waiting for NonStop may be simpler to work with. Then, rebuild > > parallel series on top of the 'master' that has the fix applied, > > perhaps? > > Yes, that is the path forward now that Randall also confirmed the fix > works on NonStop (btw thank you Randall). :) > > Just waiting for Peff to tell me if he wants to send it himself. I just sent out the fix patch, which should be good for 2.54. Here's the test patch, which I hope you'll include when re-rolling the parallel series (either as-is, or if you prefer it can be moved to another script where we're doing other parallel hook tests). It would be nice to refer to the fix commit using its id, but we won't know what it is until Junio applies it. :) So once that happens it might be worth tweaking the commit message. -- >8 -- Subject: t5401: test SIGPIPE with parallel hooks We recently fixed a bug where a hook that caused us to get SIGPIPE would accidentally trigger the run_processes_parallel() cleanup handler, killing the child processes. For a single hook, this meant killing the already-exited hook. This case was triggered by our tests, but was only a problem on some platforms. But if you have multiple hooks running in parallel, this causes a problem everywhere, since one hook failing to read its input would take down all hooks. Now that we have parallel hook support, we can add a test for this case. It should pass already, due to the existing fix. Signed-off-by: Jeff King <peff@peff.net> --- t/t5401-update-hooks.sh | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh index 44ec875aef..f727b5d545 100755 --- a/t/t5401-update-hooks.sh +++ b/t/t5401-update-hooks.sh @@ -139,4 +139,42 @@ test_expect_success 'pre-receive hook that forgets to read its input' ' git push ./victim.git "+refs/heads/*:refs/heads/*" ' +test_expect_success 'hooks in parallel that do not read input' ' + # Add this to our $PATH to avoid having to write the whole trash + # directory into our config options, which would require quoting. + mkdir bin && + PATH=$PWD/bin:$PATH && + + write_script bin/hook-fast <<-\EOF && + # This hook does not read its input, so the parent process + # may see SIGPIPE if it is not ignored. It should happen + # relatively quickly. + exit 0 + EOF + + write_script bin/hook-slow <<-\EOF && + # This hook is slow, so we expect it to still be running + # when the other hook has exited (and the parent has a pipe error + # writing to it). + # + # So we want to be slow enough that we expect this to happen, but not + # so slow that the test takes forever. 1 second is probably enough + # in practice (and if it is occasionally not on a loaded system, we + # will err on the side of having the test pass). + sleep 1 + exit 0 + EOF + + git init --bare parallel.git && + git -C parallel.git config hook.fast.command "hook-fast" && + git -C parallel.git config hook.fast.event pre-receive && + git -C parallel.git config hook.fast.parallel true && + git -C parallel.git config hook.slow.command "hook-slow" && + git -C parallel.git config hook.slow.event pre-receive && + git -C parallel.git config hook.slow.parallel true && + git -C parallel.git config hook.jobs 2 && + + git push ./parallel.git "+refs/heads/*:refs/heads/*" +' + test_done -- 2.54.0.rc1.274.g1f8c576c50 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 5:20 ` Jeff King 2026-04-08 5:43 ` Jeff King @ 2026-04-08 15:50 ` Junio C Hamano 2026-04-08 16:26 ` Adrian Ratiu 1 sibling, 1 reply; 18+ messages in thread From: Junio C Hamano @ 2026-04-08 15:50 UTC (permalink / raw) To: Jeff King; +Cc: rsbecker, Adrian Ratiu, git Jeff King <peff@peff.net> writes: > I think the root of the issue is that we should not be trying to > propagate SIGPIPE to the child in this case at all. Our handler is > pushed there only because it's part of sigchain_push_common(), which is > sensible: in general if we are dying to SIGPIPE we want to do our > cleanup. It's just funny in this case with the ordering of our SIG_IGN, > because now that SIG_IGN isn't on top of the stack anymore. > > I.e., I think we want to reorder like this: > > diff --git a/run-command.c b/run-command.c > index 32c290ee6a..8a95f7ff1e 100644 > --- a/run-command.c > +++ b/run-command.c > @@ -1895,14 +1895,19 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) > "max:%"PRIuMAX, > (uintmax_t)opts->processes); > > + pp_init(&pp, opts, &pp_sig); > + > /* > * Child tasks might receive input via stdin, terminating early (or not), so > * ignore the default SIGPIPE which gets handled by each feed_pipe_fn which > * actually writes the data to children stdin fds. > + * > + * This _must_ come after pp_init(), because it installs its own > + * SIGPIPE handler (to cleanup children), and we want to supersede > + * that. > */ > sigchain_push(SIGPIPE, SIG_IGN); > > - pp_init(&pp, opts, &pp_sig); > while (1) { > for (i = 0; > i < spawn_cap && !pp.shutdown && > > Does that make your problem go away? > > I suspect we could construct a related case that does fail on Linux > without the patch above. Imagine we actually have two hooks running in > parallel. The first one is fast and does not read its input, and the > second one is slow. We'll get SIGPIPE writing to the first one, and then > kill _both_ children. But that's wrong! There is no reason to kill the > second hook, as our intent was to ignore SIGPIPE. Oh, I am very much impressed by this analysis. As -rc1 has already been tagged (but not pushed out yet), we would probably want to apply a fix before -rc2, I suppose. Thanks. ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: Help needed on 2.54.0-rc0 t5301.13 looping. 2026-04-08 15:50 ` Help needed on 2.54.0-rc0 t5301.13 looping Junio C Hamano @ 2026-04-08 16:26 ` Adrian Ratiu 2026-04-08 17:20 ` [PATCH] run_processes_parallel(): fix order of sigpipe handling Jeff King 0 siblings, 1 reply; 18+ messages in thread From: Adrian Ratiu @ 2026-04-08 16:26 UTC (permalink / raw) To: Junio C Hamano, Jeff King; +Cc: rsbecker, git On Wed, 08 Apr 2026, Junio C Hamano <gitster@pobox.com> wrote: > Jeff King <peff@peff.net> writes: > >> I think the root of the issue is that we should not be trying to >> propagate SIGPIPE to the child in this case at all. Our handler is >> pushed there only because it's part of sigchain_push_common(), which is >> sensible: in general if we are dying to SIGPIPE we want to do our >> cleanup. It's just funny in this case with the ordering of our SIG_IGN, >> because now that SIG_IGN isn't on top of the stack anymore. >> >> I.e., I think we want to reorder like this: >> >> diff --git a/run-command.c b/run-command.c >> index 32c290ee6a..8a95f7ff1e 100644 >> --- a/run-command.c >> +++ b/run-command.c >> @@ -1895,14 +1895,19 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) >> "max:%"PRIuMAX, >> (uintmax_t)opts->processes); >> >> + pp_init(&pp, opts, &pp_sig); >> + >> /* >> * Child tasks might receive input via stdin, terminating early (or not), so >> * ignore the default SIGPIPE which gets handled by each feed_pipe_fn which >> * actually writes the data to children stdin fds. >> + * >> + * This _must_ come after pp_init(), because it installs its own >> + * SIGPIPE handler (to cleanup children), and we want to supersede >> + * that. >> */ >> sigchain_push(SIGPIPE, SIG_IGN); >> >> - pp_init(&pp, opts, &pp_sig); >> while (1) { >> for (i = 0; >> i < spawn_cap && !pp.shutdown && >> >> Does that make your problem go away? >> >> I suspect we could construct a related case that does fail on Linux >> without the patch above. Imagine we actually have two hooks running in >> parallel. The first one is fast and does not read its input, and the >> second one is slow. We'll get SIGPIPE writing to the first one, and then >> kill _both_ children. But that's wrong! There is no reason to kill the >> second hook, as our intent was to ignore SIGPIPE. > > Oh, I am very much impressed by this analysis. > > As -rc1 has already been tagged (but not pushed out yet), we would > probably want to apply a fix before -rc2, I suppose. Yes, that is fine. All my local tests also look good with Peff's patch (including the parallel series). @Peff Please let me know if you wish me to send a patch or if you wish to send it yourself, since this investigation is your work & effort. :) ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH] run_processes_parallel(): fix order of sigpipe handling 2026-04-08 16:26 ` Adrian Ratiu @ 2026-04-08 17:20 ` Jeff King 2026-04-08 17:59 ` Junio C Hamano 0 siblings, 1 reply; 18+ messages in thread From: Jeff King @ 2026-04-08 17:20 UTC (permalink / raw) To: Adrian Ratiu; +Cc: Junio C Hamano, rsbecker, git On Wed, Apr 08, 2026 at 07:26:59PM +0300, Adrian Ratiu wrote: > @Peff > > Please let me know if you wish me to send a patch or if you wish to send > it yourself, since this investigation is your work & effort. :) Here it is with a small cleanup and a real commit message. -- >8 -- Subject: run_processes_parallel(): fix order of sigpipe handling In commit ec0becacc9 (run-command: add stdin callback for parallelization, 2026-01-28), we taught run_processes_parallel() to ignore SIGPIPE, since we wouldn't want a write() to a broken pipe of one of the children to take down the whole process. But there's a subtle ordering issue. After we ignore SIGPIPE, we call pp_init(), which installs its own cleanup handler for multiple signals using sigchain_push_common(), which includes SIGPIPE. So if we receive SIGPIPE while writing to a child, we'll trigger that handler first, pop it off the stack, and then re-raise (which is then ignored because of the SIG_IGN we pushed first). But what does that handler do? It tries to clean up all of the child processes, under the assumption that when we re-raise the signal we'll be exiting the process! So a hook that exits without reading all of its input will cause us to get SIGPIPE, which will put us in a signal handler that then tries to kill() that same child. This seems to be mostly harmless on Linux. The process has already exited by this point, and though kill() does not complain (since the process has not been reaped with a wait() call), it does not affect the exit status of the process. However, this seems not to be true on all platforms. This case is triggered by t5401.13, "pre-receive hook that forgets to read its input". This test fails on NonStop since that hook was converted to the run_processes_parallel() API. We can fix it by reordering the code a bit. We should run pp_init() first, and then push our SIG_IGN onto the stack afterwards, so that it is truly ignored while feeding the sub-processes. Note that we also reorder the popping at the end of the function, too. This is not technically necessary, as we are doing two pops either way, but now the pops will correctly match their pushes. This also fixes a related case that we can't test yet. If we did have more than one process to run, then one child causing SIGPIPE would cause us to kill() all of the children (which might still actually be running). But the hook API is the only user of the new feed_pipe feature, and it does not yet support parallel hook execution. So for now we'll always execute the processes sequentially. Once parallel hook execution exists, we'll be able to add a test which covers this. Reported-by: Randall S. Becker <rsbecker@nexbridge.com> Signed-off-by: Jeff King <peff@peff.net> --- run-command.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/run-command.c b/run-command.c index 32c290ee6a..574d5c40f0 100644 --- a/run-command.c +++ b/run-command.c @@ -1895,14 +1895,19 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) "max:%"PRIuMAX, (uintmax_t)opts->processes); + pp_init(&pp, opts, &pp_sig); + /* * Child tasks might receive input via stdin, terminating early (or not), so * ignore the default SIGPIPE which gets handled by each feed_pipe_fn which * actually writes the data to children stdin fds. + * + * This _must_ come after pp_init(), because it installs its own + * SIGPIPE handler (to cleanup children), and we want to supersede + * that. */ sigchain_push(SIGPIPE, SIG_IGN); - pp_init(&pp, opts, &pp_sig); while (1) { for (i = 0; i < spawn_cap && !pp.shutdown && @@ -1928,10 +1933,10 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) } } - pp_cleanup(&pp, opts); - sigchain_pop(SIGPIPE); + pp_cleanup(&pp, opts); + if (do_trace2) trace2_region_leave(tr2_category, tr2_label, NULL); } -- 2.54.0.rc1.274.g1f8c576c50 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] run_processes_parallel(): fix order of sigpipe handling 2026-04-08 17:20 ` [PATCH] run_processes_parallel(): fix order of sigpipe handling Jeff King @ 2026-04-08 17:59 ` Junio C Hamano 2026-04-08 20:54 ` Junio C Hamano 0 siblings, 1 reply; 18+ messages in thread From: Junio C Hamano @ 2026-04-08 17:59 UTC (permalink / raw) To: Jeff King; +Cc: Adrian Ratiu, rsbecker, git Jeff King <peff@peff.net> writes: > We can fix it by reordering the code a bit. We should run pp_init() > first, and then push our SIG_IGN onto the stack afterwards, so that it > is truly ignored while feeding the sub-processes. > > Note that we also reorder the popping at the end of the function, too. > This is not technically necessary, as we are doing two pops either way, > but now the pops will correctly match their pushes. Sounds quite sensible. > This also fixes a related case that we can't test yet. If we did have > more than one process to run, then one child causing SIGPIPE would cause > us to kill() all of the children (which might still actually be > running). But the hook API is the only user of the new feed_pipe > feature, and it does not yet support parallel hook execution. So for now > we'll always execute the processes sequentially. Once parallel hook > execution exists, we'll be able to add a test which covers this. Great. > Reported-by: Randall S. Becker <rsbecker@nexbridge.com> > Signed-off-by: Jeff King <peff@peff.net> Thanks, all of you, for addressing the issue so quickly. Applied. > --- > run-command.c | 11 ++++++++--- > 1 file changed, 8 insertions(+), 3 deletions(-) > > diff --git a/run-command.c b/run-command.c > index 32c290ee6a..574d5c40f0 100644 > --- a/run-command.c > +++ b/run-command.c > @@ -1895,14 +1895,19 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) > "max:%"PRIuMAX, > (uintmax_t)opts->processes); > > + pp_init(&pp, opts, &pp_sig); > + > /* > * Child tasks might receive input via stdin, terminating early (or not), so > * ignore the default SIGPIPE which gets handled by each feed_pipe_fn which > * actually writes the data to children stdin fds. > + * > + * This _must_ come after pp_init(), because it installs its own > + * SIGPIPE handler (to cleanup children), and we want to supersede > + * that. > */ > sigchain_push(SIGPIPE, SIG_IGN); > > - pp_init(&pp, opts, &pp_sig); > while (1) { > for (i = 0; > i < spawn_cap && !pp.shutdown && > @@ -1928,10 +1933,10 @@ void run_processes_parallel(const struct run_process_parallel_opts *opts) > } > } > > - pp_cleanup(&pp, opts); > - > sigchain_pop(SIGPIPE); > > + pp_cleanup(&pp, opts); > + > if (do_trace2) > trace2_region_leave(tr2_category, tr2_label, NULL); > } ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] run_processes_parallel(): fix order of sigpipe handling 2026-04-08 17:59 ` Junio C Hamano @ 2026-04-08 20:54 ` Junio C Hamano 2026-04-08 23:42 ` Jeff King 0 siblings, 1 reply; 18+ messages in thread From: Junio C Hamano @ 2026-04-08 20:54 UTC (permalink / raw) To: Jeff King; +Cc: Adrian Ratiu, rsbecker, git Junio C Hamano <gitster@pobox.com> writes: >> Reported-by: Randall S. Becker <rsbecker@nexbridge.com> >> Signed-off-by: Jeff King <peff@peff.net> > > Thanks, all of you, for addressing the issue so quickly. > > Applied. We have a few places where we sigchain_push(SIGPIPE, SIG_IGN) then run start_command(). One is in upload-pack.c where we spawn "rev-list" for reachability check, and the other is in fetch-pack.c where we spawn unpack-objects/index-pack. Currently neither subprocess is marked with the clean-on-exit bit. but if somebody is careless and flips the bit for these subprocesses, start_command() will call mark_child_for_cleanup() and causes sigchain_push_common() to set up cleanup_children_on_signal() to be called, which would lead to a very similar bug. I wonder if swapping the order of start_command() and sigchain_push() in these two code paths have downsides, or is it making the code worse just to futureproof it against a future that is unlikely to come? ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH] run_processes_parallel(): fix order of sigpipe handling 2026-04-08 20:54 ` Junio C Hamano @ 2026-04-08 23:42 ` Jeff King 2026-04-09 13:40 ` Junio C Hamano 0 siblings, 1 reply; 18+ messages in thread From: Jeff King @ 2026-04-08 23:42 UTC (permalink / raw) To: Junio C Hamano; +Cc: Adrian Ratiu, rsbecker, git On Wed, Apr 08, 2026 at 01:54:26PM -0700, Junio C Hamano wrote: > Junio C Hamano <gitster@pobox.com> writes: > > >> Reported-by: Randall S. Becker <rsbecker@nexbridge.com> > >> Signed-off-by: Jeff King <peff@peff.net> > > > > Thanks, all of you, for addressing the issue so quickly. > > > > Applied. > > We have a few places where we sigchain_push(SIGPIPE, SIG_IGN) then > run start_command(). One is in upload-pack.c where we spawn > "rev-list" for reachability check, and the other is in fetch-pack.c > where we spawn unpack-objects/index-pack. > > Currently neither subprocess is marked with the clean-on-exit bit. > but if somebody is careless and flips the bit for these > subprocesses, start_command() will call mark_child_for_cleanup() and > causes sigchain_push_common() to set up cleanup_children_on_signal() > to be called, which would lead to a very similar bug. Hmm, good catch. This is a bit worrisome, as we've added some clean_on_exit calls recently, and might do so again. > I wonder if swapping the order of start_command() and sigchain_push() > in these two code paths have downsides, or is it making the code worse > just to futureproof it against a future that is unlikely to come? I don't think it's really making the code worse. It's putting the SIGPIPE handling closer to where we're actually doing the writes. But I don't like that it is a subtle thing that people writing new code have to worry about. And I wouldn't be surprised if there are other cases where we disable SIGPIPE, and then call start_command() in a much lower level of the call chain, which would make reordering harder. I wonder if we can do better. The root of the issue is that sigchain_push_common() is not really expressing what we want. We are trying to install a handler to do cleanup _if_ we are about to exit. And that is always going to be true for SIGTERM, etc, where we might install handlers but never expect them to rescue us from exiting. But for SIGPIPE, our desired action is really dependent on whether the signal is being ignored in general. So we could perhaps do something like this: diff --git a/sigchain.c b/sigchain.c index 66123bdbab..343b5571e0 100644 --- a/sigchain.c +++ b/sigchain.c @@ -16,7 +16,7 @@ static void check_signum(int sig) BUG("signal out of range: %d", sig); } -int sigchain_push(int sig, sigchain_fun f) +static int sigchain_push_1(int sig, sigchain_fun f, int keep_ignored) { struct sigchain_signal *s = signals + sig; check_signum(sig); @@ -25,10 +25,24 @@ int sigchain_push(int sig, sigchain_fun f) s->old[s->n] = signal(sig, f); if (s->old[s->n] == SIG_ERR) return -1; + if (keep_ignored && s->old[s->n] == SIG_IGN) { + /* + * The signal was already ignored; keep it that way + * rather than installing a handler which would be used + * for cleanup. + */ + if (signal(sig, SIG_IGN) < 0) + return -1; + } s->n++; return 0; } +int sigchain_push(int sig, sigchain_fun f) +{ + return sigchain_push_1(sig, f, 0); +} + int sigchain_pop(int sig) { struct sigchain_signal *s = signals + sig; @@ -48,7 +62,7 @@ void sigchain_push_common(sigchain_fun f) sigchain_push(SIGHUP, f); sigchain_push(SIGTERM, f); sigchain_push(SIGQUIT, f); - sigchain_push(SIGPIPE, f); + sigchain_push_1(SIGPIPE, f, 1); } void sigchain_pop_common(void) And that turns the handler setup in pp_init() into a noop (for SIGPIPE), since it sees that we're ignoring the signal already. But I think this isn't quite enough for the cases in start_command(), which have something even deeper going on. The handler we set up in mark_child_for_cleanup() is _never_ popped. The idea is that we install it once for the first child which needs it, and then the rest of the invocations just add to the cleanup list. But that breaks the push/pop paradigm if it's interleaved with other calls. I.e., if we do: sigchain_push(SIGPIPE, SIG_IGN); child.clean_on_exit = 1; start_command(&child); sigchain_pop(SIGPIPE); then that pop is not popping SIG_IGN. It's popping the cleanup handler installed by start_command! So now we're ignoring SIGPIPE forever for the rest of the process. To fix that I think we have to reconsider the push/pop idea for signals. I suspect the semantics we want are more like: - Individual subsystems may register a cleanup handler, but may never remove it. Handlers should recognize when they have no work to do and return (because they have their own lists of children to clean up, temporary files to remove, and so forth). - When a cleanup handler is registered, we add it to a linked list and register _one_ signal handler that iterates over the list, calling each cleanup handler that has been registered. - You can't install "ignore" or SIG_IGN as a cleanup handler. But... - Code can push/pop an "ignore" flag for a given signal. If a signal is marked as ignored, then that supersedes all cleanup handlers. It can be implemented either with SIG_IGN, or the signal handler can just return from the handler without exiting. That's a total rewrite of our signal handling, though. There might be details I haven't considered. As a stop-gap, I think one smaller thing we could do is just register all of those one-off handlers (like the one for start_command()) at the beginning of the program, via init_git() or similar. And then they're at the bottom of the sigchain stack, so they're never interleaved with other push/pop calls. That's kind of horrible, but I don't think there are so many that it's the end of the world. All of that is out-of-scope for -rc2, though. ;) -Peff ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH] run_processes_parallel(): fix order of sigpipe handling 2026-04-08 23:42 ` Jeff King @ 2026-04-09 13:40 ` Junio C Hamano 0 siblings, 0 replies; 18+ messages in thread From: Junio C Hamano @ 2026-04-09 13:40 UTC (permalink / raw) To: Jeff King; +Cc: Adrian Ratiu, rsbecker, git Jeff King <peff@peff.net> writes: >> Currently neither subprocess is marked with the clean-on-exit bit. >> but if somebody is careless and flips the bit for these >> subprocesses, start_command() will call mark_child_for_cleanup() and >> causes sigchain_push_common() to set up cleanup_children_on_signal() >> to be called, which would lead to a very similar bug. > > Hmm, good catch. This is a bit worrisome, as we've added some > clean_on_exit calls recently, and might do so again. > >> I wonder if swapping the order of start_command() and sigchain_push() >> in these two code paths have downsides, or is it making the code worse >> just to futureproof it against a future that is unlikely to come? > > I don't think it's really making the code worse. It's putting the > SIGPIPE handling closer to where we're actually doing the writes. But I > don't like that it is a subtle thing that people writing new code have > to worry about. And I wouldn't be surprised if there are other cases > where we disable SIGPIPE, and then call start_command() in a much lower > level of the call chain, which would make reordering harder. OK. Such a change is easy, compared to anything we try to do better ;-). > I wonder if we can do better. > > The root of the issue is that sigchain_push_common() is not really > expressing what we want. We are trying to install a handler to do > cleanup _if_ we are about to exit. And that is always going to be true > for SIGTERM, etc, where we might install handlers but never expect them > to rescue us from exiting. But for SIGPIPE, our desired action is really > dependent on whether the signal is being ignored in general. Hmph, I actually was hoping that we do not have to go in the route that each specific signal differently, but I guess it is unavoidable as they come with their own semantics (somewhat similar to the way how their default disposition has to be different). > That's a total rewrite of our signal handling, though. There might be > details I haven't considered. > > All of that is out-of-scope for -rc2, though. ;) Of course. ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2026-04-09 13:40 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-07 23:37 Help needed on 2.54.0-rc0 t5301.13 looping rsbecker 2026-04-08 5:20 ` Jeff King 2026-04-08 5:43 ` Jeff King 2026-04-08 11:53 ` Adrian Ratiu 2026-04-08 15:44 ` rsbecker 2026-04-08 15:52 ` rsbecker 2026-04-08 15:55 ` rsbecker 2026-04-08 16:53 ` Junio C Hamano 2026-04-08 16:58 ` rsbecker 2026-04-08 17:01 ` Adrian Ratiu 2026-04-08 17:30 ` [PATCH] t5401: test SIGPIPE with parallel hooks Jeff King 2026-04-08 15:50 ` Help needed on 2.54.0-rc0 t5301.13 looping Junio C Hamano 2026-04-08 16:26 ` Adrian Ratiu 2026-04-08 17:20 ` [PATCH] run_processes_parallel(): fix order of sigpipe handling Jeff King 2026-04-08 17:59 ` Junio C Hamano 2026-04-08 20:54 ` Junio C Hamano 2026-04-08 23:42 ` Jeff King 2026-04-09 13:40 ` Junio C Hamano
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.