From ed78249ad5f3bf44777d0bdd39bb3f1a2890239d Mon Sep 17 00:00:00 2001 From: "t.feng" Date: Mon, 2 Aug 2021 15:07:01 +0600 Subject: [PATCH] fix deadlock when forking in multithread --- pyanaconda/core/glib.py | 19 +++++++++++++++++-- pyanaconda/payload/dnf/payload.py | 15 +++++++++++---- pyanaconda/payload/dnf/utils.py | 2 ++ .../ui/gui/spokes/installation_progress.py | 4 ++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/pyanaconda/core/glib.py b/pyanaconda/core/glib.py index 03c598d..e1cb8db 100644 --- a/pyanaconda/core/glib.py +++ b/pyanaconda/core/glib.py @@ -33,9 +33,10 @@ from gi.repository.GLib import markup_escape_text, format_size_full, \ MainLoop, MainContext, \ GError, Variant, VariantType, Bytes, \ IOCondition, IOChannel, SpawnFlags, \ - MAXUINT + MAXUINT, Mutex -__all__ = ["create_main_loop", "create_new_context", +__all__ = ["glib_mutex", "run_with_mutex", + "create_main_loop", "create_new_context", "markup_escape_text", "format_size_full", "timeout_add_seconds", "timeout_add", "idle_add", "io_add_watch", "child_watch_add", @@ -46,6 +47,9 @@ __all__ = ["create_main_loop", "create_new_context", "MAXUINT"] +glib_mutex = Mutex() + + def create_main_loop(): """Create GLib main loop. @@ -59,3 +63,14 @@ def create_new_context(): :returns: GLib.MainContext.""" return MainContext.new() + + +def run_with_mutex(func): + """run in glib mutex + """ + def _call_method(*args, **kwargs): + glib_mutex.lock() + func(*args, **kwargs) + glib_mutex.unlock() + return _call_method + diff --git a/pyanaconda/payload/dnf/payload.py b/pyanaconda/payload/dnf/payload.py index 45003da..0145a62 100644 --- a/pyanaconda/payload/dnf/payload.py +++ b/pyanaconda/payload/dnf/payload.py @@ -36,6 +36,7 @@ import libdnf.repo import rpm import re import pyanaconda.localization +import time from blivet.size import Size from dnf.const import GROUP_PACKAGE_TYPES @@ -84,6 +85,7 @@ from pyanaconda.progress import progressQ, progress_message from pyanaconda.simpleconfig import SimpleConfigFile from pyanaconda.ui.lib.payload import get_payload, get_source, create_source, set_source, \ set_up_sources, tear_down_sources +from pyanaconda.core.glib import glib_mutex log = get_packaging_logger() @@ -1327,10 +1329,15 @@ class DNFPayload(Payload): pre_msg = (N_("Preparing transaction from installation source")) progress_message(pre_msg) - queue_instance = multiprocessing.Queue() - process = multiprocessing.Process(target=do_transaction, - args=(self._base, queue_instance)) - process.start() + while True: + if glib_mutex.trylock(): + queue_instance = multiprocessing.Queue() + process = multiprocessing.Process(target=do_transaction, + args=(self._base, queue_instance)) + process.start() + glib_mutex.unlock() + break + time.sleep(0.5) (token, msg) = queue_instance.get() # When the installation works correctly it will get 'install' updates # followed by a 'post' message and then a 'quit' message. diff --git a/pyanaconda/payload/dnf/utils.py b/pyanaconda/payload/dnf/utils.py index dfac5c9..0d7c10c 100644 --- a/pyanaconda/payload/dnf/utils.py +++ b/pyanaconda/payload/dnf/utils.py @@ -27,6 +27,7 @@ from pyanaconda.progress import progressQ from pyanaconda.core import util from pyanaconda.core.configuration.anaconda import conf from pyanaconda.product import productName, productVersion +from pyanaconda.core.glib import glib_mutex log = get_packaging_logger() @@ -126,6 +127,7 @@ def do_transaction(base, queue_instance): # always raise a BaseException, so presence of 'quit' without a preceeding # 'post' message also indicates a problem. try: + glib_mutex.unlock() display = TransactionProgress(queue_instance) base.do_transaction(display=display) exit_reason = "DNF quit" diff --git a/pyanaconda/ui/gui/spokes/installation_progress.py b/pyanaconda/ui/gui/spokes/installation_progress.py index 0de742b..2ca0f67 100644 --- a/pyanaconda/ui/gui/spokes/installation_progress.py +++ b/pyanaconda/ui/gui/spokes/installation_progress.py @@ -29,6 +29,7 @@ from pykickstart.constants import KS_SHUTDOWN, KS_REBOOT from pyanaconda.ui.gui.hubs.summary import SummaryHub from pyanaconda.ui.gui.spokes import StandaloneSpoke from pyanaconda.ui.gui.utils import gtk_call_once +from pyanaconda.core.glib import run_with_mutex log = get_module_logger(__name__) @@ -185,12 +186,14 @@ class ProgressSpoke(StandaloneSpoke): log.debug("The installation has started.") + @run_with_mutex def _init_progress_bar(self, steps): self._totalSteps = steps self._currentStep = 0 gtk_call_once(self._progressBar.set_fraction, 0.0) + @run_with_mutex def _step_progress_bar(self): if not self._totalSteps: return @@ -198,6 +201,7 @@ class ProgressSpoke(StandaloneSpoke): self._currentStep += 1 gtk_call_once(self._progressBar.set_fraction, self._currentStep/self._totalSteps) + @run_with_mutex def _update_progress_message(self, message): if not self._totalSteps: return -- 2.23.0