summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dan@archlinux.org>2011-09-28 01:53:43 -0500
committerDan McGee <dan@archlinux.org>2011-09-28 04:52:37 -0500
commit40a264478e65c652f863b3e43b0fc8aa10f0bd19 (patch)
tree4f0774d7e13583dca6a3e181d29f0e9c38dc009b
parent6e081a0c57f0f6f14428f7cb78bb22f6848fe4af (diff)
downloadpacman-40a264478e65c652f863b3e43b0fc8aa10f0bd19.tar.xz
Track unresolvable transaction packages
Rather than free them right away, keep the list on the transaction as we already do with add and remove lists. This is necessary because we may be manipulating pointers the frontend needs to refer to packages, and we are breaking our contract as stated in the alpm_add_pkg() documentation of only freeing packages at the end of a transaction. This fixes an issue found when refactoring the package list display code. Signed-off-by: Dan McGee <dan@archlinux.org>
-rw-r--r--lib/libalpm/sync.c19
-rw-r--r--lib/libalpm/trans.c3
-rw-r--r--lib/libalpm/trans.h5
3 files changed, 18 insertions, 9 deletions
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index fd48ef37..8c50ec88 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -439,9 +439,11 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
}
}
- /* Unresolvable packages will be removed from the target list, so
- we free the transaction specific fields */
- alpm_list_free_inner(unresolvable, (alpm_list_fn_free)_alpm_pkg_free_trans);
+ /* Unresolvable packages will be removed from the target list; set these
+ * aside in the transaction as a list we won't operate on. If we free them
+ * before the end of the transaction, we may kill pointers the frontend
+ * holds to package objects. */
+ trans->unresolvable = unresolvable;
/* re-order w.r.t. dependencies */
alpm_list_free(trans->add);
@@ -508,7 +510,8 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
_("removing '%s' from target list because it conflicts with '%s'\n"),
rsync->name, sync->name);
trans->add = alpm_list_remove(trans->add, rsync, _alpm_pkg_cmp, NULL);
- _alpm_pkg_free_trans(rsync); /* rsync is not transaction target anymore */
+ /* rsync is not a transaction target anymore */
+ trans->unresolvable = alpm_list_add(trans->unresolvable, rsync);
continue;
}
@@ -610,7 +613,6 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
}
cleanup:
- alpm_list_free(unresolvable);
alpm_list_free(remove);
return ret;
@@ -1026,9 +1028,12 @@ static int load_packages(alpm_handle_t *handle, alpm_list_t **data,
continue;
}
free(filepath);
- pkgfile->reason = spkg->reason; /* copy over install reason */
+ /* copy over the install reason */
+ pkgfile->reason = spkg->reason;
i->data = pkgfile;
- _alpm_pkg_free_trans(spkg); /* spkg has been removed from the target list */
+ /* spkg has been removed from the target list, so we can free the
+ * sync-specific fields */
+ _alpm_pkg_free_trans(spkg);
}
PROGRESS(handle, ALPM_PROGRESS_LOAD_START, "", 100,
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index a5fa95b9..fbc5feec 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -236,6 +236,9 @@ void _alpm_trans_free(alpm_trans_t *trans)
return;
}
+ alpm_list_free_inner(trans->unresolvable,
+ (alpm_list_fn_free)_alpm_pkg_free_trans);
+ alpm_list_free(trans->unresolvable);
alpm_list_free_inner(trans->add, (alpm_list_fn_free)_alpm_pkg_free_trans);
alpm_list_free(trans->add);
alpm_list_free_inner(trans->remove, (alpm_list_fn_free)_alpm_pkg_free);
diff --git a/lib/libalpm/trans.h b/lib/libalpm/trans.h
index a2be5a5c..38f45ff7 100644
--- a/lib/libalpm/trans.h
+++ b/lib/libalpm/trans.h
@@ -39,8 +39,9 @@ typedef enum _alpm_transstate_t {
struct __alpm_trans_t {
alpm_transflag_t flags;
alpm_transstate_t state;
- alpm_list_t *add; /* list of (alpm_pkg_t *) */
- alpm_list_t *remove; /* list of (alpm_pkg_t *) */
+ alpm_list_t *unresolvable; /* list of (alpm_pkg_t *) */
+ alpm_list_t *add; /* list of (alpm_pkg_t *) */
+ alpm_list_t *remove; /* list of (alpm_pkg_t *) */
alpm_list_t *skip_remove; /* list of (char *) */
};