update_manager: fix blocking I/O

When using tempfile.TemporaryDirectory it is possible that
exiting the context will block when attempting to delete
the temporary directory.  Don't use the context manager,
instead create and cleanup the temp dir using the default
threadpoolexecutor.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Eric Callahan 2022-02-28 19:30:34 -05:00
parent faf956c65d
commit 27466984df
No known key found for this signature in database
GPG Key ID: 7027245FBBDDF59A
2 changed files with 17 additions and 7 deletions

View File

@ -602,6 +602,13 @@ class CommandHelper:
self.notify_update_response( self.notify_update_response(
f"Downloading {self.cur_update_app}: {totals} [{progress}%]") f"Downloading {self.cur_update_app}: {totals} [{progress}%]")
async def create_tempdir(self, suffix=None, prefix=None):
def _createdir(sfx, pfx):
return tempfile.TemporaryDirectory(suffix=sfx, prefix=pfx)
eventloop = self.server.get_event_loop()
return await eventloop.run_in_thread(_createdir, suffix, prefix)
class PackageDeploy(BaseDeploy): class PackageDeploy(BaseDeploy):
def __init__(self, def __init__(self,
config: ConfigHelper, config: ConfigHelper,
@ -1218,9 +1225,9 @@ class WebClientDeploy(BaseDeploy):
f"Updating Web Client {self.name}...") f"Updating Web Client {self.name}...")
self.cmd_helper.notify_update_response( self.cmd_helper.notify_update_response(
f"Downloading Client: {self.name}") f"Downloading Client: {self.name}")
with tempfile.TemporaryDirectory( td = await self.cmd_helper.create_tempdir(self.name, "client")
suffix=self.name, prefix="client") as tempdirname: try:
tempdir = pathlib.Path(tempdirname) tempdir = pathlib.Path(td.name)
temp_download_file = tempdir.joinpath(f"{self.name}.zip") temp_download_file = tempdir.joinpath(f"{self.name}.zip")
temp_persist_dir = tempdir.joinpath(self.name) temp_persist_dir = tempdir.joinpath(self.name)
client = self.cmd_helper.get_http_client() client = self.cmd_helper.get_http_client()
@ -1232,6 +1239,8 @@ class WebClientDeploy(BaseDeploy):
await event_loop.run_in_thread( await event_loop.run_in_thread(
self._extract_release, temp_persist_dir, self._extract_release, temp_persist_dir,
temp_download_file) temp_download_file)
finally:
await event_loop.run_in_thread(td.cleanup)
self.version = self.remote_version self.version = self.remote_version
version_path = self.path.joinpath(".version") version_path = self.path.joinpath(".version")
if not version_path.exists(): if not version_path.exists():

View File

@ -11,7 +11,6 @@ import json
import shutil import shutil
import re import re
import time import time
import tempfile
import zipfile import zipfile
from .app_deploy import AppDeploy from .app_deploy import AppDeploy
from utils import verify_source from utils import verify_source
@ -378,9 +377,9 @@ class ZipDeploy(AppDeploy):
npm_hash = await self._get_file_hash(self.npm_pkg_json) npm_hash = await self._get_file_hash(self.npm_pkg_json)
dl_url, content_type, size = self.release_download_info dl_url, content_type, size = self.release_download_info
self.notify_status("Starting Download...") self.notify_status("Starting Download...")
with tempfile.TemporaryDirectory( td = await self.cmd_helper.create_tempdir(self.name, "app")
suffix=self.name, prefix="app") as tempdirname: try:
tempdir = pathlib.Path(tempdirname) tempdir = pathlib.Path(td.name)
temp_download_file = tempdir.joinpath(f"{self.name}.zip") temp_download_file = tempdir.joinpath(f"{self.name}.zip")
client = self.cmd_helper.get_http_client() client = self.cmd_helper.get_http_client()
await client.download_file( await client.download_file(
@ -391,6 +390,8 @@ class ZipDeploy(AppDeploy):
event_loop = self.server.get_event_loop() event_loop = self.server.get_event_loop()
await event_loop.run_in_thread( await event_loop.run_in_thread(
self._extract_release, temp_download_file) self._extract_release, temp_download_file)
finally:
await event_loop.run_in_thread(td.cleanup)
await self._update_dependencies(npm_hash, force=force_dep_update) await self._update_dependencies(npm_hash, force=force_dep_update)
await self._update_repo_state() await self._update_repo_state()
await self.restart_service() await self.restart_service()