On Thu, Jun 06, 2024 at 06:19:25PM -0400, Taylor Blau wrote: > @@ -2035,24 +2035,23 @@ static int write_commit_graph_file(struct write_commit_graph_context *ctx) > LOCK_DIE_ON_ERROR, 0444); > free(lock_name); > > - fd = git_mkstemp_mode(ctx->graph_name, 0444); > - if (fd < 0) { > + graph_layer = mks_tempfile_m(ctx->graph_name, 0444); > + if (!graph_layer) { > error(_("unable to create temporary graph layer")); > return -1; > } > > - if (adjust_shared_perm(ctx->graph_name)) { > + if (adjust_shared_perm(get_tempfile_path(graph_layer))) { > error(_("unable to adjust shared permissions for '%s'"), > - ctx->graph_name); > + get_tempfile_path(graph_layer)); > return -1; > } Most errors will cause us to die(), but this "return" and the one that Junio noted later (when renaming the base graph file fails) mean we'll return with the tempfile still active. We'll clean it up when the program exits, but if there were a long-running program that called write_commit_graph_file(), that tempfile might hang around longer than necessary. But that is the same strategy that the existing code uses for the lock we use for the chain filename! And it is much worse there, because now it is not just a tempfile hanging around, but we're blocking anybody else from taking the lock. So I think it would be OK to punt on this for now. Your patch is not making the situation worse, and it's all a problem for a hypothetical libification of this function. > +test_expect_success 'temporary graph layer is discarded upon failure' ' > + git init layer-discard && > + ( > + cd layer-discard && > + > + test_commit A && > + test_commit B && > + > + # Intentionally remove commit "A" from the object store > + # so that the commit-graph machinery fails to parse the > + # parents of "B". > + # > + # This takes place after the commit-graph machinery has > + # initialized a new temporary file to store the contents > + # of the new graph layer, so will allow us to ensure > + # that the temporary file is discarded upon failure. > + rm $objdir/$(test_oid_to_path $(git rev-parse HEAD^)) && > + > + test_must_fail git commit-graph write --reachable --split && > + test_dir_is_empty $graphdir > + ) > +' I'm glad you were able to come up with a case that fails cleanly and non-racily. The exit code of rev-parse will be lost. I doubt that it matters in practice, but I wouldn't be surprised if our shell linting eventually learns to complain about this spot. Looks like there are a few similar ones in the test suite already, from t5329. I'd be content to leave it for now and deal with it later if somebody really wants to go on a crusade against lost exit codes. -Peff