action_utils: Don't restart web interface when installing an app

Tests:

- systemd-run --pipe
--property=BindReadOnlyPaths=/usr/share/freedombox/etc/needrestart/conf.d/freedombox-self.conf:/etc/needrestart/conf.d/freedombox-self.conf
ls -la /etc/needrestart/conf.d/ shows that the new configuration is listed as
expected.

- Running about command with 'cat /etc/needrestart/conf.d/freedombox-self.conf'
shows that configuration content is as expected.

- Running functional tests for coturn app work as expected. systemd journal
shows that transient services are being created to run apt commands.

- After the execution of an operation an empty file is created as
/etc/needrestart/conf.d/freedombox-self.conf.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2026-03-18 20:27:09 -07:00 committed by James Valleroy
parent 0e698eb4b4
commit db92e23c75
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
3 changed files with 39 additions and 3 deletions

View File

@ -437,9 +437,31 @@ def is_disk_image():
return os.path.exists('/var/lib/freedombox/is-freedombox-disk-image')
def run_apt_command(arguments, enable_triggers: bool = False):
def run_apt_command(arguments, enable_triggers: bool = False,
allow_freedombox_restart=False):
"""Run apt-get with provided arguments."""
command = ['apt-get', '--assume-yes', '--quiet=2'] + arguments
command = []
if not allow_freedombox_restart:
# Don't restart the freedombox web service. This configuration is only
# used when apt command is invoked from freedombox web service itself
# (such as during an app's installation/uninstallation).
#
# If this is not done, a freedombox web service restart is attempted.
# needsrestart will wait until the restart is completed. apt command
# will wait until needsrestart is completed. The restart mechanism in
# service will wait until all currently running threads are completed.
# One thread that has invoked this apt command will not finish as it
# waits for apt command to finish. This results in a deadlock. Avoid
# this by not attempting to restart freedombox web service when apt
# command is invoked from freedombox web service.
mount_path = '/etc/needrestart/conf.d/freedombox-self.conf'
orig_path = f'/usr/share/freedombox{mount_path}'
command = [
'systemd-run', '--pipe',
f'--property=BindReadOnlyPaths={orig_path}:{mount_path}'
]
command += ['apt-get', '--assume-yes', '--quiet=2'] + arguments
env = os.environ.copy()
env['DEBIAN_FRONTEND'] = 'noninteractive'

View File

@ -0,0 +1,13 @@
# Don't restart the freedombox web service. This configuration is only used when
# apt command is invoked from freedombox web service itself (such as during an
# app's installation/uninstallation).
#
# If this is not done, a freedombox web service restart is attempted.
# needsrestart will wait until the restart is completed. apt command will wait
# until needsrestart is completed. The restart mechanism in service will wait
# until all currently running threads are completed. One thread that has invoked
# this apt command will not finish as it waits for apt command to finish. This
# results in a deadlock. Avoid this by not attempting to restart freedombox web
# service when apt command is invoked from freedombox web service.
$nrconf{override_rc}->{qr(^freedombox\.service$)} = 0;
$nrconf{override_rc}->{qr(^plinth\.service$)} = 0;

View File

@ -72,7 +72,8 @@ distribution_info: dict = {
def _apt_run(arguments: list[str]):
"""Run an apt command and ensure that output is written to stdout."""
returncode = action_utils.run_apt_command(arguments)
returncode = action_utils.run_apt_command(arguments,
allow_freedombox_restart=True)
if returncode:
raise RuntimeError(
f'Apt command failed with return code: {returncode}')