Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wait for all background threads to finish before filling installation… #3722

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 25 additions & 18 deletions pyanaconda/installation.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from pyanaconda.kickstart import runPostScripts, runPreInstallScripts
from pyanaconda.kexec import setup_kexec
from pyanaconda.installation_tasks import Task, TaskQueue, DBusTask
from pyanaconda.progress import progressQ
from pykickstart.constants import SNAPSHOT_WHEN_POST_INSTALL

from pyanaconda.anaconda_loggers import get_module_logger
Expand Down Expand Up @@ -214,6 +215,25 @@ def run_generate_initramfs():
return configuration_queue


def wait_for_threads_to_finish():
"""Wait for background processing threads to finish.

Wait for background processing threads to finish before filling
the installation task queue. Otherwise installation tasks might
be created based on old data in DBus modules, missing data set by
the threads that are still running.
"""

# This should be the only thread running, wait for the others to finish if not.
if threadMgr.running > 1:
# show a progress message
progressQ.send_message(N_("Waiting for %s threads to finish") % (threadMgr.running - 1))
for message in ("Thread %s is running" % n for n in threadMgr.names):
log.debug(message)
threadMgr.wait_all()
log.debug("No more threads are running, assembling installation task queue.")


def _prepare_installation(payload, ksdata):
"""Perform an installation. This method takes the ksdata as prepared by
the UI (the first hub, in graphical mode) and applies it to the disk.
Expand All @@ -225,24 +245,6 @@ def _prepare_installation(payload, ksdata):
installation_queue.queue_started.connect(lambda x: progress_message(x.status_message))
installation_queue.task_completed.connect(lambda x: progress_step(x.name))

# This should be the only thread running, wait for the others to finish if not.
if threadMgr.running > 1:
# it could be that the threads finish execution before the task is executed,
# but that should not cause any issues

def wait_for_all_treads():
for message in ("Thread %s is running" % n for n in threadMgr.names):
log.debug(message)
threadMgr.wait_all()

# Use a queue with a single task as only TaskQueues have the status_message
# property used for setting the progress status in the UI.
wait_for_threads = TaskQueue("Wait for threads to finish",
N_("Waiting for %s threads to finish") % (threadMgr.running - 1))

wait_for_threads.append(Task("Wait for all threads to finish", wait_for_all_treads))
installation_queue.append(wait_for_threads)

# Save system time to HW clock.
# - this used to be before waiting on threads, but I don't think that's needed
if conf.system.can_set_hardware_clock:
Expand Down Expand Up @@ -359,6 +361,11 @@ def run_install_bootloader():

def run_installation(payload, ksdata):
"""Run the complete installation."""
# before building the install task queue make
# sure no backgrond processing threads are running and
# the Anaconda internal state is thus final
wait_for_threads_to_finish()

queue = TaskQueue("Complete installation queue")
queue.append(_prepare_installation(payload, ksdata))
queue.append(_prepare_configuration(payload, ksdata))
Expand Down