dcavalca / rpms / rpm

Forked from rpms/rpm 2 years ago
Clone
Blob Blame History Raw
From 531dc8495cd3aabd3f659ecab604106fdbacbe98 Mon Sep 17 00:00:00 2001
Message-Id: <531dc8495cd3aabd3f659ecab604106fdbacbe98.1554974459.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 3 Oct 2018 11:51:38 +0300
Subject: [PATCH] Fix ancient python GIL locking bug on callback
 (RhBug:1632488)

Introduced in commit c7881d801745b4c156a8aa2afc17b95f97481e34 back in 2002,
synthesizing a python object for the callback occurs before retaking
the GIL lock, which is not allowed. Somehow this has managed to stay
latent all these years, and even now requires fairly specific conditions:
when the callback gets called without an associated key, such as erasures
or file trigger script start/stop events (in the case of RhBug:1632488),
when Python 3 is running in PYTHONMALLOC=debug mode,
it crashes with "Python memory allocator called without holding the GIL".

Simply retake the lock before any Python operations take place to fix.
---
 python/rpmts-py.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/python/rpmts-py.c b/python/rpmts-py.c
index e4c5e1250..1ddfc9a1e 100644
--- a/python/rpmts-py.c
+++ b/python/rpmts-py.c
@@ -495,6 +495,8 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
 
     if (cbInfo->cb == Py_None) return NULL;
 
+    PyEval_RestoreThread(cbInfo->_save);
+
     /* Synthesize a python object for callback (if necessary). */
     if (pkgObj == NULL) {
 	if (h) {
@@ -506,8 +508,6 @@ rpmtsCallback(const void * hd, const rpmCallbackType what,
     } else
 	Py_INCREF(pkgObj);
 
-    PyEval_RestoreThread(cbInfo->_save);
-
     args = Py_BuildValue("(iLLOO)", what, amount, total, pkgObj, cbInfo->data);
     result = PyEval_CallObject(cbInfo->cb, args);
     Py_DECREF(args);
-- 
2.20.1