[Bug 263879] pkgbase removes critical etc files upon upgrade
- In reply to: bugzilla-noreply_a_freebsd.org: "[Bug 263879] pkgbase removes critical etc files upon upgrade"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 04 Oct 2022 16:25:53 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=263879 --- Comment #4 from Mark Johnston <markj@FreeBSD.org> --- I spent some time reading the libpkg job scheduler and I think I see part of the problem, but I'm not sure yet how to fix it. Basically, upon an upgrade I get a conflict on /etc/termcap.small between FreeBSD-runtime(local) and FreeBSD-utilities(remote). When handling the conflict, pkg decides to split the upgrade of -runtime into separate uninstall and install jobs, which wipes my /etc files. But, obviously we can avoid the conflict by simply upgrading -runtime before -utilities; the split is not needed. And, pkg schedules the uninstall/install of -runtime back-to-back anyway, so it's no different from an upgrade. After pkg has figured out which jobs (i.e. package installs/upgrades/removals) it will execute, it assigns priorities to determine the execution order. This happens in pkg_jobs_set_priorities(). If there's a conflict on a package being deleted as part of an upgrade, pkg bumps the priorities of both the deletion and the addition jobs: 770 if (rit->priority >= req->items[1]->priority) { 771 pkg_jobs_update_universe_item_priority(universe, req->items[1], 772 rit->priority + 1, PKG_PRIORITY_UPDATE_CONFLICT); 773 /* 774 * Update priorities for a remote part as well 775 */ 776 pkg_jobs_update_universe_item_priority(universe, req->items[0], 777 req->items[0]->priority, PKG_PRIORITY_UPDATE_REQUEST); 778 } pkg_jobs_update_universe_item_priority() recursively updates the priorities of dependent jobs. However, it also has this check which I do not quite understand: 668 if ((item->next != NULL || item->prev != NULL) && 669 it->pkg->type != PKG_INSTALLED && 670 (type == PKG_PRIORITY_UPDATE_CONFLICT || 671 type == PKG_PRIORITY_UPDATE_DELETE)) { 672 /* 673 * We do not update priority of a remote part of conflict, as we know 674 * that remote packages should not contain conflicts (they should be 675 * resolved in request prior to calling of this function) 676 */ 677 pkg_debug(2, "skip update priority for %s-%s", 678 it->pkg->uid, it->pkg->digest); 679 continue; 680 } In my case, it causes installation of the remote FreeBSD-runtime to have lower priority than removal of the local FreeBSD-runtime package. This causes pkg to split the job. Commenting out this block "fixes" my problem, but I can't tell if it actually affects correctness of the code, or if it's just an optimization, or... BTW, this behaviour is highly dependent on the order in which packages are loaded into various lists. If I fetch packages first, then cancel the upgrade, then try to upgrade again, I get different behaviour from the job scheduler. So it's not too surprising that others may not observe the problem. What's an example of an upgrade where a package really does need to be split? Consider two packages p1, p2 with files a and b respectively, and suppose that new versions of those packages switch ownership, so p1 contains b and p2 contains a. Then to upgrade, we have to uninstall one of p1 or p2, upgrade the other, then install the missing package. This situation can arise in the base system, so how do we handle the case where two critical pkgbase packages are entangled this way? -- You are receiving this mail because: You are the assignee for the bug.