Blame SOURCES/0002-Fix-attaching-and-detaching-of-libsolvRepo.patch

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();