c39ca3
From 2a4e2782a1faaf8e7bf5d4123e572007e591d24b Mon Sep 17 00:00:00 2001
c39ca3
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
c39ca3
Date: Tue, 23 Apr 2019 10:07:59 +0200
c39ca3
Subject: [PATCH] Prevent race condition when --update & we have duplicate pkgs
c39ca3
 (RhBug: 1696808)
c39ca3
c39ca3
---
c39ca3
 src/createrepo_c.c  |  2 ++
c39ca3
 src/dumper_thread.c | 12 ++++++++----
c39ca3
 src/dumper_thread.h |  1 +
c39ca3
 3 files changed, 11 insertions(+), 4 deletions(-)
c39ca3
c39ca3
diff --git a/src/createrepo_c.c b/src/createrepo_c.c
c39ca3
index 444d88f..160789b 100644
c39ca3
--- a/src/createrepo_c.c
c39ca3
+++ b/src/createrepo_c.c
c39ca3
@@ -995,6 +995,7 @@ main(int argc, char **argv)
c39ca3
     user_data.id_oth            = 0;
c39ca3
     user_data.buffer            = g_queue_new();
c39ca3
     user_data.mutex_buffer      = g_mutex_new();
c39ca3
+    user_data.mutex_old_md      = g_mutex_new();
c39ca3
     user_data.deltas            = cmd_options->deltas;
c39ca3
     user_data.max_delta_rpm_size= cmd_options->max_delta_rpm_size;
c39ca3
     user_data.mutex_deltatargetpackages = g_mutex_new();
c39ca3
@@ -1049,6 +1050,7 @@ main(int argc, char **argv)
c39ca3
 
c39ca3
     g_queue_free(user_data.buffer);
c39ca3
     g_mutex_free(user_data.mutex_buffer);
c39ca3
+    g_mutex_free(user_data.mutex_old_md);
c39ca3
     g_cond_free(user_data.cond_pri);
c39ca3
     g_cond_free(user_data.cond_fil);
c39ca3
     g_cond_free(user_data.cond_oth);
c39ca3
diff --git a/src/dumper_thread.c b/src/dumper_thread.c
c39ca3
index 27c2493..589ab52 100644
c39ca3
--- a/src/dumper_thread.c
c39ca3
+++ b/src/dumper_thread.c
c39ca3
@@ -436,9 +436,15 @@ cr_dumper_thread(gpointer data, gpointer user_data)
c39ca3
     // Update stuff
c39ca3
     if (udata->old_metadata) {
c39ca3
         // We have old metadata
c39ca3
+        g_mutex_lock(udata->mutex_old_md);
c39ca3
         md = (cr_Package *) g_hash_table_lookup(
c39ca3
                                 cr_metadata_hashtable(udata->old_metadata),
c39ca3
                                 task->filename);
c39ca3
+        // Remove the pkg from the hash table of old metadata, so that no other
c39ca3
+        // thread can use it as CACHE, because later we modify it destructively
c39ca3
+        g_hash_table_steal(cr_metadata_hashtable(udata->old_metadata),
c39ca3
+                                                 task->filename);
c39ca3
+        g_mutex_unlock(udata->mutex_old_md);
c39ca3
 
c39ca3
         if (md) {
c39ca3
             g_debug("CACHE HIT %s", task->filename);
c39ca3
@@ -576,8 +582,7 @@ cr_dumper_thread(gpointer data, gpointer user_data)
c39ca3
     write_pkg(task->id, res, pkg, udata);
c39ca3
 
c39ca3
     // Clean up
c39ca3
-    if (pkg != md)
c39ca3
-        cr_package_free(pkg);
c39ca3
+    cr_package_free(pkg);
c39ca3
     g_free(res.primary);
c39ca3
     g_free(res.filelists);
c39ca3
     g_free(res.other);
c39ca3
@@ -623,8 +628,7 @@ cr_dumper_thread(gpointer data, gpointer user_data)
c39ca3
             // Dump XML and SQLite
c39ca3
             write_pkg(buf_task->id, buf_task->res, buf_task->pkg, udata);
c39ca3
             // Clean up
c39ca3
-            if (!buf_task->pkg_from_md)
c39ca3
-                cr_package_free(buf_task->pkg);
c39ca3
+            cr_package_free(buf_task->pkg);
c39ca3
             g_free(buf_task->res.primary);
c39ca3
             g_free(buf_task->res.filelists);
c39ca3
             g_free(buf_task->res.other);
c39ca3
diff --git a/src/dumper_thread.h b/src/dumper_thread.h
c39ca3
index 94a57d8..74d5951 100644
c39ca3
--- a/src/dumper_thread.h
c39ca3
+++ b/src/dumper_thread.h
c39ca3
@@ -71,6 +71,7 @@ struct UserData {
c39ca3
     // Update stuff
c39ca3
     gboolean skip_stat;             // Skip stat() while updating
c39ca3
     cr_Metadata *old_metadata;      // Loaded metadata
c39ca3
+    GMutex *mutex_old_md;           // Mutex for accessing old metadata
c39ca3
 
c39ca3
     // Thread serialization
c39ca3
     GMutex *mutex_pri;              // Mutex for primary metadata