From 9c57347931e135dffd040cc0fd04f5211ea76821 Mon Sep 17 00:00:00 2001 From: James Valleroy Date: Wed, 23 Jun 2021 18:12:47 -0400 Subject: [PATCH] action_utils: Use flag to indicate freedombox package has been held In case the plinth process is interrupted, the "finally" block that is meant to unhold the package may not be executed, and the package will stay held. The flag is used to indicate this situation, so it can be resolved the next time apt_hold_freedombox is used. Tests: - (normal) No hold on freedombox package, and flag is not set. Install any app. Afterwards, there is no hold, and flag is not set. - (admin preference) Place hold on freedombox package, but flag is not set. Install any app. Afterwards, there is still a hold, but flag is not set. - (recovery) Place hold on freedombox package, but flag is set. Install any app. Afterwards, there is no hold, and flag is not set. Signed-off-by: James Valleroy --- plinth/action_utils.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/plinth/action_utils.py b/plinth/action_utils.py index 8ee808233..aed8e5a3f 100644 --- a/plinth/action_utils.py +++ b/plinth/action_utils.py @@ -5,6 +5,7 @@ Python action utility functions. import logging import os +import pathlib import shutil import subprocess import tempfile @@ -428,11 +429,23 @@ def apt_hold(packages, ignore_errors=False): @contextmanager def apt_hold_freedombox(): """Prevent freedombox package from being removed during apt operations.""" + # This flag is a backup indicator that we held the package, in + # case the process is interrupted and the 'finally' is not run. + apt_hold_flag = pathlib.Path('/var/lib/freedombox/package-held') current_hold = subprocess.check_output( ['apt-mark', 'showhold', 'freedombox']) try: - yield current_hold or subprocess.check_call( - ['apt-mark', 'hold', 'freedombox']) + if current_hold: + # Package is already held, possibly by administrator. + yield current_hold + else: + # Set the flag. + apt_hold_flag.touch(mode=0o660) + yield subprocess.check_call(['apt-mark', 'hold', 'freedombox']) finally: - if not current_hold: + # Was the package held, either in this process or a previous one? + if not current_hold or apt_hold_flag.exists(): subprocess.check_call(['apt-mark', 'unhold', 'freedombox']) + # Clear the flag. + if apt_hold_flag.exists(): + apt_hold_flag.unlink()