update_manager: fix race condition

Previously the Klipper repo location can be changed outside of
the lock.  If the location of the Klipper path is moved while an autorefresh is occurring it is possible for Moonraker to call refresh
and/or notify_update_refreshed before the repo has been initialized.

This commit moves the re-assignment of the "klipper" updated inside
the lock.  In addition AppDeploy._is_valid is now defined in the
__init__() method.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2024-01-06 11:54:33 -05:00
parent 84a8538597
commit 6e6388d673
No known key found for this signature in database
GPG Key ID: 5A1EB336DFB4C71B
2 changed files with 7 additions and 6 deletions

View File

@ -76,6 +76,7 @@ class AppDeploy(BaseDeploy):
f"option 'channel'. Type '{self.type}' supports the following "
f"channels: {str_channels}. Falling back to channel '{self.channel}'"
)
self._is_valid: bool = False
self.virtualenv: Optional[pathlib.Path] = None
self.py_exec: Optional[pathlib.Path] = None
self.pip_cmd: Optional[str] = None

View File

@ -210,18 +210,18 @@ class UpdateManager:
kcfg.set_option("path", kpath)
kcfg.set_option("env", executable)
kcfg.set_option("type", str(app_type))
need_notification = not isinstance(kupdater, AppDeploy)
notify = not isinstance(kupdater, AppDeploy)
kclass = get_deploy_class(app_type, BaseDeploy)
self.updaters['klipper'] = kclass(kcfg, self.cmd_helper)
coro = self._update_klipper_repo(need_notification)
coro = self._update_klipper_repo(kclass(kcfg, self.cmd_helper), notify)
self.event_loop.create_task(coro)
async def _update_klipper_repo(self, notify: bool) -> None:
async def _update_klipper_repo(self, updater: BaseDeploy, notify: bool) -> None:
async with self.cmd_request_lock:
self.updaters['klipper'] = updater
umdb = self.cmd_helper.get_umdb()
await umdb.pop('klipper', None)
await self.updaters['klipper'].initialize()
await self.updaters['klipper'].refresh()
await updater.initialize()
await updater.refresh()
if notify:
self.cmd_helper.notify_update_refreshed()