commit 12f5a70b8d705757d7a6740303ba2c2aa4df930f from: Stefan Sperling date: Fri Aug 15 11:28:22 2025 UTC better fix for long loop bug during commit coloring with offloading Repaint already queued commits in the main process instead of removing them from the queue. Otherwise we may never converge to a state where all commits are marked as skipped. Instead such commits can inherit color keep and we'll keep on asking got-read-pack to paint more commits for a very long time. ok op@ commit - 5abe061a03aa6b587c595d904418740002d94956 commit + 12f5a70b8d705757d7a6740303ba2c2aa4df930f blob - 9afa74d1d08cfdfe6e45e1bd1911a37c1585184b blob + c29bd335ba24926a633d0fdfb8bbfb2624c42d73 --- lib/pack_create_privsep.c +++ lib/pack_create_privsep.c @@ -219,7 +219,7 @@ recv_painted_commit(void *arg, struct got_object_id *i { const struct got_error *err = NULL; struct recv_painted_commit_arg *a = arg; - struct got_object_qid *qid, *tmp; + struct got_object_qid *qid; if (a->cancel_cb) { err = a->cancel_cb(a->cancel_arg); @@ -256,17 +256,18 @@ recv_painted_commit(void *arg, struct got_object_id *i "%s invalid commit color %"PRIdPTR, __func__, color); } - STAILQ_FOREACH_SAFE(qid, a->ids, entry, tmp) { + STAILQ_FOREACH(qid, a->ids, entry) { + int ocolor; if (got_object_id_cmp(&qid->id, id) != 0) continue; - STAILQ_REMOVE(a->ids, qid, got_object_qid, entry); - color = (intptr_t)qid->data; - if (*(a->qid0) == qid) - *(a->qid0) = NULL; - got_object_qid_free(qid); - (*a->nqueued)--; - if (color == COLOR_SKIP) - (*a->nskip)--; + ocolor = (intptr_t)qid->data; + if (ocolor != color) { + got_pack_paint_commit(qid, color); + if (ocolor == COLOR_SKIP) + (*a->nskip)--; + else if (color == COLOR_SKIP) + (*a->nskip)++; + } break; }