[pacman-dev] memleak caused by "don't duplicate package in cache"

Xavier shiningxc at gmail.com
Wed Feb 6 10:07:40 EST 2008

Previously, all installed packages were duplicated when added to the cache.
in libalpm/add.c :
801 >-if(_alpm_db_add_pkgincache(db, newpkg) == -1) {

And the _alpm_db_add_pkgincache function in cache.c duplicated the newpkg.

I wanted to avoid this duplication with the following commit :

I simply removed the pkg_dup in that function. Since I removed a 
pkg_dup, I had to remove the corresponding pkg_free call also.

Previously, the packages in the targets list were freed in the 
_alpm_trans_free function. And the duplicated package in the cache were 
freed in _alpm_db_free_pkgcache.
Since the cache is freed only when alpm is released, which happens at 
the very end, I let the free there. So I removed it from 
_alpm_trans_free, which is called when a transaction is released.

Now the ugly part begins. The targets are only added to the cache when 
they are installed, not when they are removed (obviously). That explains 
the condition I added in trans_free :
+       } else if (trans->type == PM_TRANS_TYPE_REMOVE ||
+                       trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {

So, when a whole install transaction goes fine, without errors, 
everything works well. All targets are added to the cache, and are then 
all freed correctly by the _alpm_db_free_pkgcache function.
However, when the transaction doesn't go correctly, the targets are 
loaded in memory, but they are not installed, and so not freed! All 
targets stay in memory, and cause a big memleak.
For example, a conflict could be detected, and the transaction is 
aborted (as in sync400).
But it might even be possible that a transaction gets aborted in the 
middle. Maybe because it ran out of memory, or because the user 
interrupted it, or whatever.

So, for solving this issue, maybe we would need a way to track down 
which packages were loaded in the cache. That should allow us to free 
everything correctly, which doesn't seem possible currently.
We could then free in the trans_free function all targets that are not 
in the pkg cache. And the remaining targets that are in the pkg cache 
will be freed when the cache is freed.

More information about the pacman-dev mailing list