|
|
885e9e |
From d267539801ce0a32392d3a86d94e6ea37b6dc2ba Mon Sep 17 00:00:00 2001
|
|
|
885e9e |
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
|
885e9e |
Date: Fri, 12 Jul 2019 06:51:25 +0200
|
|
|
885e9e |
Subject: [PATCH 1/5] [context] Fix: Correctly detach libsolv repo
|
|
|
885e9e |
(RhBug:1727343)
|
|
|
885e9e |
|
|
|
885e9e |
Seting repoImpl->libsolvRepo = nullptr and repoImpl->nrefs = 1 is not sufficient.
|
|
|
885e9e |
The libsolvRepo inernally points back to us. And during destroying
|
|
|
885e9e |
it destroy us too because nrefs was set to 1.
|
|
|
885e9e |
Solution is to do full detach using detachLibsolvRepo().
|
|
|
885e9e |
|
|
|
885e9e |
It fixes https://bugzilla.redhat.com/show_bug.cgi?id=1727343
|
|
|
885e9e |
and probably https://bugzilla.redhat.com/show_bug.cgi?id=1727424
|
|
|
885e9e |
---
|
|
|
885e9e |
libdnf/dnf-repo.cpp | 4 ++--
|
|
|
885e9e |
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
885e9e |
|
|
|
885e9e |
diff --git a/libdnf/dnf-repo.cpp b/libdnf/dnf-repo.cpp
|
|
|
885e9e |
index a358356a9..45c6c7e5b 100644
|
|
|
885e9e |
--- a/libdnf/dnf-repo.cpp
|
|
|
885e9e |
+++ b/libdnf/dnf-repo.cpp
|
|
|
885e9e |
@@ -1403,9 +1403,9 @@ dnf_repo_check_internal(DnfRepo *repo,
|
|
|
885e9e |
}
|
|
|
885e9e |
|
|
|
885e9e |
/* init */
|
|
|
885e9e |
- repoImpl->libsolvRepo = nullptr;
|
|
|
885e9e |
+ if (repoImpl->libsolvRepo)
|
|
|
885e9e |
+ repoImpl->detachLibsolvRepo();
|
|
|
885e9e |
repoImpl->needs_internalizing = false;
|
|
|
885e9e |
- repoImpl->nrefs = 1;
|
|
|
885e9e |
repoImpl->state_main = _HY_NEW;
|
|
|
885e9e |
repoImpl->state_filelists = _HY_NEW;
|
|
|
885e9e |
repoImpl->state_presto = _HY_NEW;
|
|
|
885e9e |
|
|
|
885e9e |
From f1e2e534d7d375d051c4eae51431c5bb3649f9f1 Mon Sep 17 00:00:00 2001
|
|
|
885e9e |
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
|
885e9e |
Date: Fri, 12 Jul 2019 07:59:15 +0200
|
|
|
885e9e |
Subject: [PATCH 2/5] [Repo] Remove unused delReference
|
|
|
885e9e |
|
|
|
885e9e |
---
|
|
|
885e9e |
libdnf/repo/Repo.cpp | 7 -------
|
|
|
885e9e |
libdnf/repo/Repo.hpp | 2 --
|
|
|
885e9e |
2 files changed, 9 deletions(-)
|
|
|
885e9e |
|
|
|
885e9e |
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
index 23638839a..fd2415fa5 100644
|
|
|
885e9e |
--- a/libdnf/repo/Repo.cpp
|
|
|
885e9e |
+++ b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
@@ -1441,13 +1441,6 @@ std::vector<std::string> Repo::getMirrors() const
|
|
|
885e9e |
return mirrors;
|
|
|
885e9e |
}
|
|
|
885e9e |
|
|
|
885e9e |
-void Repo::delReference()
|
|
|
885e9e |
-{
|
|
|
885e9e |
- if (--pImpl->nrefs > 0)
|
|
|
885e9e |
- return;
|
|
|
885e9e |
- delete this;
|
|
|
885e9e |
-}
|
|
|
885e9e |
-
|
|
|
885e9e |
int PackageTargetCB::end(TransferStatus status, const char * msg) { return 0; }
|
|
|
885e9e |
int PackageTargetCB::progress(double totalToDownload, double downloaded) { return 0; }
|
|
|
885e9e |
int PackageTargetCB::mirrorFailure(const char *msg, const char *url) { return 0; }
|
|
|
885e9e |
diff --git a/libdnf/repo/Repo.hpp b/libdnf/repo/Repo.hpp
|
|
|
885e9e |
index cbf4ed147..785c6e9d5 100644
|
|
|
885e9e |
--- a/libdnf/repo/Repo.hpp
|
|
|
885e9e |
+++ b/libdnf/repo/Repo.hpp
|
|
|
885e9e |
@@ -275,8 +275,6 @@ struct Repo {
|
|
|
885e9e |
|
|
|
885e9e |
~Repo();
|
|
|
885e9e |
|
|
|
885e9e |
- void delReference();
|
|
|
885e9e |
-
|
|
|
885e9e |
class Impl;
|
|
|
885e9e |
private:
|
|
|
885e9e |
friend struct PackageTarget;
|
|
|
885e9e |
|
|
|
885e9e |
From 4c35d135bc79939d58844e99e0d5ed924ba86fd5 Mon Sep 17 00:00:00 2001
|
|
|
885e9e |
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
|
885e9e |
Date: Fri, 12 Jul 2019 08:50:54 +0200
|
|
|
885e9e |
Subject: [PATCH 3/5] [Repo] Add locking and asserts
|
|
|
885e9e |
|
|
|
885e9e |
Add locking and asserts into attachLibsolvRepo(), detachLibsolvRepo()
|
|
|
885e9e |
and hy_repo_free()
|
|
|
885e9e |
---
|
|
|
885e9e |
libdnf/dnf-repo.cpp | 3 +--
|
|
|
885e9e |
libdnf/repo/Repo-private.hpp | 5 +++++
|
|
|
885e9e |
libdnf/repo/Repo.cpp | 34 ++++++++++++++++++++++++++--------
|
|
|
885e9e |
3 files changed, 32 insertions(+), 10 deletions(-)
|
|
|
885e9e |
|
|
|
885e9e |
diff --git a/libdnf/dnf-repo.cpp b/libdnf/dnf-repo.cpp
|
|
|
885e9e |
index 45c6c7e5b..c30d99d17 100644
|
|
|
885e9e |
--- a/libdnf/dnf-repo.cpp
|
|
|
885e9e |
+++ b/libdnf/dnf-repo.cpp
|
|
|
885e9e |
@@ -1403,8 +1403,7 @@ dnf_repo_check_internal(DnfRepo *repo,
|
|
|
885e9e |
}
|
|
|
885e9e |
|
|
|
885e9e |
/* init */
|
|
|
885e9e |
- if (repoImpl->libsolvRepo)
|
|
|
885e9e |
- repoImpl->detachLibsolvRepo();
|
|
|
885e9e |
+ repoImpl->detachLibsolvRepo();
|
|
|
885e9e |
repoImpl->needs_internalizing = false;
|
|
|
885e9e |
repoImpl->state_main = _HY_NEW;
|
|
|
885e9e |
repoImpl->state_filelists = _HY_NEW;
|
|
|
885e9e |
diff --git a/libdnf/repo/Repo-private.hpp b/libdnf/repo/Repo-private.hpp
|
|
|
885e9e |
index 23acf3622..333eb7bfd 100644
|
|
|
885e9e |
--- a/libdnf/repo/Repo-private.hpp
|
|
|
885e9e |
+++ b/libdnf/repo/Repo-private.hpp
|
|
|
885e9e |
@@ -43,6 +43,7 @@
|
|
|
885e9e |
|
|
|
885e9e |
#include <cctype>
|
|
|
885e9e |
#include <map>
|
|
|
885e9e |
+#include <mutex>
|
|
|
885e9e |
#include <set>
|
|
|
885e9e |
|
|
|
885e9e |
#include <string.h>
|
|
|
885e9e |
@@ -177,6 +178,10 @@ class Repo::Impl {
|
|
|
885e9e |
int main_nrepodata{0};
|
|
|
885e9e |
int main_end{0};
|
|
|
885e9e |
|
|
|
885e9e |
+ // Lock attachLibsolvRepo(), detachLibsolvRepo() and hy_repo_free() to ensure atomic behavior
|
|
|
885e9e |
+ // in threaded environment such as PackageKit.
|
|
|
885e9e |
+ std::mutex attachLibsolvMutex;
|
|
|
885e9e |
+
|
|
|
885e9e |
private:
|
|
|
885e9e |
Repo * owner;
|
|
|
885e9e |
std::unique_ptr<LrResult> lrHandlePerform(LrHandle * handle, const std::string & destDirectory,
|
|
|
885e9e |
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
index fd2415fa5..86531fe9b 100644
|
|
|
885e9e |
--- a/libdnf/repo/Repo.cpp
|
|
|
885e9e |
+++ b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
@@ -60,7 +60,6 @@
|
|
|
885e9e |
#include <iostream>
|
|
|
885e9e |
#include <list>
|
|
|
885e9e |
#include <map>
|
|
|
885e9e |
-#include <mutex>
|
|
|
885e9e |
#include <set>
|
|
|
885e9e |
#include <sstream>
|
|
|
885e9e |
#include <type_traits>
|
|
|
885e9e |
@@ -1335,8 +1334,10 @@ LrHandle * Repo::Impl::getCachedHandle()
|
|
|
885e9e |
|
|
|
885e9e |
void Repo::Impl::attachLibsolvRepo(LibsolvRepo * libsolvRepo)
|
|
|
885e9e |
{
|
|
|
885e9e |
+ std::lock_guard<std::mutex> guard(attachLibsolvMutex);
|
|
|
885e9e |
+ assert(!this->libsolvRepo);
|
|
|
885e9e |
++nrefs;
|
|
|
885e9e |
- libsolvRepo->appdata = owner;
|
|
|
885e9e |
+ libsolvRepo->appdata = owner; // The libsolvRepo references back to us.
|
|
|
885e9e |
libsolvRepo->subpriority = -owner->getCost();
|
|
|
885e9e |
libsolvRepo->priority = -owner->getPriority();
|
|
|
885e9e |
this->libsolvRepo = libsolvRepo;
|
|
|
885e9e |
@@ -1344,11 +1345,23 @@ void Repo::Impl::attachLibsolvRepo(LibsolvRepo * libsolvRepo)
|
|
|
885e9e |
|
|
|
885e9e |
void Repo::Impl::detachLibsolvRepo()
|
|
|
885e9e |
{
|
|
|
885e9e |
- libsolvRepo->appdata = nullptr;
|
|
|
885e9e |
- if (--nrefs > 0)
|
|
|
885e9e |
- this->libsolvRepo = nullptr;
|
|
|
885e9e |
- else
|
|
|
885e9e |
+ attachLibsolvMutex.lock();
|
|
|
885e9e |
+ if (!libsolvRepo) {
|
|
|
885e9e |
+ // Nothing to do, libsolvRepo is not attached.
|
|
|
885e9e |
+ attachLibsolvMutex.unlock();
|
|
|
885e9e |
+ return;
|
|
|
885e9e |
+ }
|
|
|
885e9e |
+
|
|
|
885e9e |
+ libsolvRepo->appdata = nullptr; // Removes reference to this object from libsolvRepo.
|
|
|
885e9e |
+ this->libsolvRepo = nullptr;
|
|
|
885e9e |
+
|
|
|
885e9e |
+ if (--nrefs <= 0) {
|
|
|
885e9e |
+ // There is no reference to this object, we are going to destroy it.
|
|
|
885e9e |
+ // Mutex is part of this object, we must unlock it before destroying.
|
|
|
885e9e |
+ attachLibsolvMutex.unlock();
|
|
|
885e9e |
delete owner;
|
|
|
885e9e |
+ } else
|
|
|
885e9e |
+ attachLibsolvMutex.unlock();
|
|
|
885e9e |
}
|
|
|
885e9e |
|
|
|
885e9e |
void Repo::setMaxMirrorTries(int maxMirrorTries)
|
|
|
885e9e |
@@ -2057,7 +2070,12 @@ hy_repo_get_string(HyRepo repo, int which)
|
|
|
885e9e |
void
|
|
|
885e9e |
hy_repo_free(HyRepo repo)
|
|
|
885e9e |
{
|
|
|
885e9e |
- if (--libdnf::repoGetImpl(repo)->nrefs > 0)
|
|
|
885e9e |
- return;
|
|
|
885e9e |
+ auto repoImpl = libdnf::repoGetImpl(repo);
|
|
|
885e9e |
+ {
|
|
|
885e9e |
+ std::lock_guard<std::mutex> guard(repoImpl->attachLibsolvMutex);
|
|
|
885e9e |
+ if (--repoImpl->nrefs > 0)
|
|
|
885e9e |
+ return; // There is still a reference to this object. Don't destroy it.
|
|
|
885e9e |
+ }
|
|
|
885e9e |
+ assert(!repoImpl->libsolvRepo);
|
|
|
885e9e |
delete repo;
|
|
|
885e9e |
}
|
|
|
885e9e |
|
|
|
885e9e |
From 3a61d4c590612427bfeb7302236e4429acae90b0 Mon Sep 17 00:00:00 2001
|
|
|
885e9e |
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
|
885e9e |
Date: Fri, 12 Jul 2019 11:21:48 +0200
|
|
|
885e9e |
Subject: [PATCH 4/5] Fix: crash in repo_internalize_trigger() without HyRepo
|
|
|
885e9e |
attached
|
|
|
885e9e |
|
|
|
885e9e |
The repo_internalize_trigger() uses needs_internalizing from HyRepo.
|
|
|
885e9e |
If HyRepo is not attached we will assume needs_internalizing==true.
|
|
|
885e9e |
---
|
|
|
885e9e |
libdnf/repo/Repo.cpp | 10 +++++++---
|
|
|
885e9e |
1 file changed, 7 insertions(+), 3 deletions(-)
|
|
|
885e9e |
|
|
|
885e9e |
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
index 86531fe9b..210ecde8f 100644
|
|
|
885e9e |
--- a/libdnf/repo/Repo.cpp
|
|
|
885e9e |
+++ b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
@@ -1826,15 +1826,19 @@ repo_internalize_all_trigger(Pool *pool)
|
|
|
885e9e |
void
|
|
|
885e9e |
repo_internalize_trigger(Repo * repo)
|
|
|
885e9e |
{
|
|
|
885e9e |
- if (repo) {
|
|
|
885e9e |
- auto hrepo = static_cast<HyRepo>(repo->appdata);
|
|
|
885e9e |
+ if (!repo)
|
|
|
885e9e |
+ return;
|
|
|
885e9e |
+
|
|
|
885e9e |
+ if (auto hrepo = static_cast<HyRepo>(repo->appdata)) {
|
|
|
885e9e |
+ // HyRepo is attached. The hint needs_internalizing will be used.
|
|
|
885e9e |
auto repoImpl = libdnf::repoGetImpl(hrepo);
|
|
|
885e9e |
assert(repoImpl->libsolvRepo == repo);
|
|
|
885e9e |
if (!repoImpl->needs_internalizing)
|
|
|
885e9e |
return;
|
|
|
885e9e |
repoImpl->needs_internalizing = false;
|
|
|
885e9e |
- repo_internalize(repo);
|
|
|
885e9e |
}
|
|
|
885e9e |
+
|
|
|
885e9e |
+ repo_internalize(repo);
|
|
|
885e9e |
}
|
|
|
885e9e |
|
|
|
885e9e |
void
|
|
|
885e9e |
|
|
|
885e9e |
From e4cabf803e1dbb6283330636d06ccb4a26e89ad4 Mon Sep 17 00:00:00 2001
|
|
|
885e9e |
From: Jaroslav Rohel <jrohel@redhat.com>
|
|
|
885e9e |
Date: Sun, 14 Jul 2019 10:45:27 +0200
|
|
|
885e9e |
Subject: [PATCH 5/5] [Repo] attachLibsolvRepo() can reattach repo to another
|
|
|
885e9e |
libsolvRepo
|
|
|
885e9e |
|
|
|
885e9e |
---
|
|
|
885e9e |
libdnf/repo/Repo.cpp | 10 ++++++++--
|
|
|
885e9e |
1 file changed, 8 insertions(+), 2 deletions(-)
|
|
|
885e9e |
|
|
|
885e9e |
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
index 210ecde8f..70c6a7411 100644
|
|
|
885e9e |
--- a/libdnf/repo/Repo.cpp
|
|
|
885e9e |
+++ b/libdnf/repo/Repo.cpp
|
|
|
885e9e |
@@ -1335,8 +1335,14 @@ LrHandle * Repo::Impl::getCachedHandle()
|
|
|
885e9e |
void Repo::Impl::attachLibsolvRepo(LibsolvRepo * libsolvRepo)
|
|
|
885e9e |
{
|
|
|
885e9e |
std::lock_guard<std::mutex> guard(attachLibsolvMutex);
|
|
|
885e9e |
- assert(!this->libsolvRepo);
|
|
|
885e9e |
- ++nrefs;
|
|
|
885e9e |
+
|
|
|
885e9e |
+ if (this->libsolvRepo)
|
|
|
885e9e |
+ // A libsolvRepo was attached to this object before. Remove it's reference to this object.
|
|
|
885e9e |
+ this->libsolvRepo->appdata = nullptr;
|
|
|
885e9e |
+ else
|
|
|
885e9e |
+ // The libsolvRepo will reference this object. Increase reference counter.
|
|
|
885e9e |
+ ++nrefs;
|
|
|
885e9e |
+
|
|
|
885e9e |
libsolvRepo->appdata = owner; // The libsolvRepo references back to us.
|
|
|
885e9e |
libsolvRepo->subpriority = -owner->getCost();
|
|
|
885e9e |
libsolvRepo->priority = -owner->getPriority();
|