Bug#1078608: apt update silently leaves old index data

Ben Hutchings <[email protected]>
Newsgroups gmane.linux.debian.apt.devel
Message-ID <707a24086fc6ca65906dfc35ab3db6aed53dc43d.camel__6951.63865327544$1747521567$gmane$org@decadent.org.uk>
On Sun, 2025-04-27 at 16:18 +0200, Ben Hutchings wrote:
[...]
> - If I mask packagekit.service before booting (using a rescue shell), 
>   then none of the files are updated automatically.  Running 'apt
>   update' updates them all as expected.
> 
> So it seems like this problem may be specific to PackageKit.
> 
> Sven and Laurent, do your affected systems have PackageKit installed?

OK, so I think this is confirmed as somehow PackageKit-related.

I had a look through the code for "apt update" and the PackageKit APT
back-end to see what might be different.  I think this has something to
do with the different pkgAcquireStatus subclasses they use, but I
couldn't identify a specific bug in PackageKit.

I experimented with writing a test program that implements its own
pkgAcquireStatus, and I I'm attaching the source for that.  It needs to
be run on a system where a local InRelease file is out of date.  If you
answer "no" to the Pulse() after the *second* time the InRelease file is
reported done, that should reproduce the broken state.

(The default answers are set for my VM snapshot which now has very
outdated InRelease files, so I know that the Pulse() after a
ReleaseInfoChanges() is the place to stop.)

Ben.

-- 
Ben Hutchings
If at first you don't succeed, you're doing about average.
apt-bug-1078608.cpp (text/x-c++src, 2.9 KB)
#include <iostream>
#include <utility>

#include <apt-pkg/acquire.h>
#include <apt-pkg/cachefile.h>
#include <apt-pkg/init.h>
#include <apt-pkg/macros.h>
#include <apt-pkg/pkgsystem.h>
#include <apt-pkg/sourcelist.h>
#include <apt-pkg/update.h>

bool ask_continue(bool answer)
{
    char ch = 0;

    std::cout << "continue? "
	      << (answer ? "[yes]/no" : "yes/[no]")
	      << "\n";

    while (std::cin.get(ch) && ch != '\n') {
	if (ch == 'y' || ch == 'Y')
	    answer = true;
	if (ch == 'n' || ch == 'N')
	    answer = false;
    }

    return answer;
}

class StatusHandler : public pkgAcquireStatus
{
public:
    StatusHandler()
    {
	Update = true;
	cancel_next_= false;
    }

private:
    bool cancel_next_;

    virtual void Fetched(unsigned long long Size,
			 unsigned long long ResumePoint) override
    {
	std::cout << "Fetched: " << Size << "\n";
	pkgAcquireStatus::Fetched(Size, ResumePoint);
    }

    virtual bool MediaChange(std::string /*Media*/,
			     std::string /*Drive*/) override
    {
	std::cerr << "MediaChange: returning false\n";
	return false;
    }

    virtual bool ReleaseInfoChanges(
	metaIndex const * const LastRelease,
	metaIndex const * const CurrentRelease,
	std::vector<ReleaseInfoChange> &&Changes) override
    {
	std::cout << "ReleaseInfoChanges\n";
	bool def_answer = pkgAcquireStatus::ReleaseInfoChanges(
	    LastRelease, CurrentRelease, std::move(Changes));
	cancel_next_ = true;
	return ask_continue(def_answer);
    }

    virtual void IMSHit(pkgAcquire::ItemDesc &/*Itm*/) override
    {
	std::cout << "IMSHit\n";
    }

    virtual void Fetch(pkgAcquire::ItemDesc &Itm) override
    {
	std::cout << "Fetch: " << Itm.URI << "\n";
    }

    virtual void Done(pkgAcquire::ItemDesc &Itm) override
    {
	std::cout << "Done: " << Itm.URI << "\n";
    }

    virtual void Fail(pkgAcquire::ItemDesc &Itm) override
    {
	std::cerr << "Fail: " << Itm.URI << "\n";
    }

    virtual bool Pulse(pkgAcquire *Owner) override
    {
	std::cout << "Pulse\n";
	bool def_answer = pkgAcquireStatus::Pulse(Owner);
	if (cancel_next_) {
	    def_answer = false;
	    cancel_next_ = false;
	}
	return ask_continue(def_answer);
    }
	
    virtual void Start() override
    {
	std::cout << "Start\n";
	pkgAcquireStatus::Start();
    }
    
    virtual void Stop() override
    {
	std::cout << "Stop\n";
	pkgAcquireStatus::Stop();
    }
};

int main(void)
{
    pkgCacheFile Cache;

    if (!pkgInitConfig(*_config)) {
	std::cerr << "pkgInitConfig() failed\n";
	return 1;
    }

    if (!pkgInitSystem(*_config, _system)) {
	std::cerr << "pkgInitSystem() failed\n";
	return 1;
    }
    
    if (!Cache.BuildSourceList()) {
	std::cerr << "BuildSourceList() failed\n";
        return 1;
    }

    StatusHandler Stat;

    if (!ListUpdate(Stat, *Cache.GetSourceList()))
	std::cerr << "ListUpdate() failed\n";
 
    pkgCacheFile::RemoveCaches();
    if (!Cache.BuildCaches() == false) {
	std::cerr << "BuildCaches() failed\n";
        return 1;
    }

    return 0;
}
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEErCspvTSmr92z9o8157/I7JWGEQkFAmgpD7kACgkQ57/I7JWG
EQkAkxAAmOKxxqQRYXDmhOODk8GxuoP9IaA1yckT4+5y360lSOExBgz+iO2eJoi/
vMUnC+V+foPg8k4MEOvmlSSWtkUtt+SUoWI0/9/AA9OydQv5ZcHGsjVs0PpuNvyT
rztuAbcGQ+Oe2bVXoJpoPCkkWhUeZCb7SYXTfYRj7D+EFH3EM5rDxT+QMZMRVD4T
AEygLToc56HqPMR9bH9QtzG79aNdmq1EsfZDM9ti8TtCQzHb+jUzFIBQikMaSirF
keYPJlRMmEHu5/2zGKi9aYJwjSNtEeDLRHbIXl/azf0gvtttJ9ApseBJGhhw0R/9
/XANhSbKgLIYHrlDSSZaQqqwcjtKxq1HqeU9e8Gno3GhaZBLkmZMoUvUTN/RFSyR
0ane596sB+XBzecn8waXaB7iQLwHo7NQOdNBvc+XlyEkHcN+vbd3ZwKaGP6QE0VP
NqtG4VNm/tmTMp38rzMZBI0C9ja8I2DaSNc4/EZkWm9REngsMi810UfGUV0S3aie
bDrmv+X9LQA1qgdzsx+OhDH6CfldBjHr1JTyQTN4iXHVD4+FFqcZcLZjmy371I2D
o0ubzfn9jhcGQnSWL9AHybF5sHv+QOdtbGiaS5xD4nTZmenepvwzx7BJgR26xMfV
UlJ8zY1SgrOI3/9QK1tZw3Kb5rOVOXuDewBUYiWS1C7QdolSdFc=
=IH4f
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.