Merge pull request #824 from mwhudson/no-new-event-loops

refactor startup a bit
This commit is contained in:
Michael Hudson-Doyle 2020-09-18 10:45:53 +12:00 committed by GitHub
commit 1881f34018
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 38 deletions

View File

@ -45,7 +45,7 @@ from subiquitycore.utils import (
from subiquity.common.errorreport import ErrorReportKind
from subiquity.controller import SubiquityTuiController
from subiquity.journald import journald_listener
from subiquity.journald import journald_listen
from subiquity.ui.views.installprogress import ProgressView
@ -260,10 +260,10 @@ class InstallProgressController(SubiquityTuiController):
self.install_state = InstallState.RUNNING
self.curtin_event_contexts[''] = context
journal_fd, watcher = journald_listener(
journald_listen(
self.app.aio_loop,
[self._event_syslog_identifier, self._log_syslog_identifier],
self._journal_event)
self.app.aio_loop.add_reader(journal_fd, watcher)
curtin_cmd = self._get_curtin_command()

View File

@ -13,6 +13,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import asyncio
import logging
import os
import platform
@ -45,7 +46,7 @@ from subiquity.common.errorreport import (
ErrorReporter,
ErrorReportKind,
)
from subiquity.journald import journald_listener
from subiquity.journald import journald_listen
from subiquity.keycodes import (
DummyKeycodesFilter,
KeyCodesFilter,
@ -134,10 +135,10 @@ class Subiquity(TuiApplication):
else:
self.input_filter = DummyKeycodesFilter()
self.journal_fd, self.journal_watcher = journald_listener(
["subiquity"], self.subiquity_event, seek=True)
self.help_menu = HelpMenu(self)
super().__init__(opts)
journald_listen(
self.aio_loop, ["subiquity"], self.subiquity_event, seek=True)
self.event_listeners = []
self.install_lock_file = Lockfile(self.state_path("installing"))
self.global_overlays = []
@ -194,7 +195,8 @@ class Subiquity(TuiApplication):
def restart(self, remove_last_screen=True):
if remove_last_screen:
self._remove_last_screen()
self.urwid_loop.screen.stop()
if self.urwid_loop is not None:
self.urwid_loop.screen.stop()
cmdline = ['snap', 'run', 'subiquity']
if self.opts.dry_run:
cmdline = [
@ -219,7 +221,7 @@ class Subiquity(TuiApplication):
tty = '/dev/' + work[len('console='):].split(',')[0]
return tty
def load_autoinstall_config(self):
async def load_autoinstall_config(self):
with open(self.opts.autoinstall) as fp:
self.autoinstall_config = yaml.safe_load(fp)
primary_tty = self.get_primary_tty()
@ -252,9 +254,7 @@ class Subiquity(TuiApplication):
while not os.path.exists(stamp_file):
time.sleep(1)
elif not os.path.exists(stamp_file):
self.aio_loop.run_until_complete(
self.controllers.Early.run())
self.new_event_loop()
await self.controllers.Early.run()
open(stamp_file, 'w').close()
with open(self.opts.autoinstall) as fp:
self.autoinstall_config = yaml.safe_load(fp)
@ -272,19 +272,20 @@ class Subiquity(TuiApplication):
# in next_screen below will be confusing.
os.system('stty sane')
def new_event_loop(self):
super().new_event_loop()
self.aio_loop.add_reader(self.journal_fd, self.journal_watcher)
async def start(self):
if self.opts.autoinstall is not None:
await self.load_autoinstall_config()
if not self.interactive() and not self.opts.dry_run:
open('/run/casper-no-prompt', 'w').close()
await super().start(start_urwid=self.interactive())
if not self.interactive():
self.select_initial_screen(0)
def extra_urwid_loop_args(self):
return dict(input_filter=self.input_filter.filter)
def run(self):
try:
if self.opts.autoinstall is not None:
self.load_autoinstall_config()
if not self.interactive() and not self.opts.dry_run:
open('/run/casper-no-prompt', 'w').close()
super().run()
except Exception:
print("generating crash report")
@ -299,8 +300,9 @@ class Subiquity(TuiApplication):
traceback.print_exc()
Error = getattr(self.controllers, "Error", None)
if Error is not None and Error.cmds:
self.new_event_loop()
self.aio_loop.run_until_complete(Error.run())
new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)
new_loop.run_until_complete(Error.run())
if self.interactive():
self._remove_last_screen()
raise

View File

@ -16,7 +16,7 @@
from systemd import journal
def journald_listener(identifiers, callback, seek=False):
def journald_listen(loop, identifiers, callback, seek=False):
reader = journal.Reader()
args = []
for identifier in identifiers:
@ -31,4 +31,4 @@ def journald_listener(identifiers, callback, seek=False):
return
for event in reader:
callback(event)
return reader.fileno(), watch
loop.add_reader(reader.fileno(), watch)

View File

@ -74,7 +74,8 @@ class Application:
self.updated = os.path.exists(self.state_path('updating'))
self.signal = Signal()
self.prober = prober
self.new_event_loop()
self.aio_loop = asyncio.get_event_loop()
self.aio_loop.set_exception_handler(self._exception_handler)
self.controllers = ControllerSet(
self.controllers_mod, self.controllers, init_args=(self,))
self.context = Context.new(self)
@ -87,12 +88,6 @@ class Application:
else:
loop.default_exception_handler(context)
def new_event_loop(self):
new_loop = asyncio.new_event_loop()
new_loop.set_exception_handler(self._exception_handler)
asyncio.set_event_loop(new_loop)
self.aio_loop = new_loop
def _connect_base_signals(self):
"""Connect signals used in the core controller."""
# Registers signals from each controller
@ -139,13 +134,16 @@ class Application:
with open(state_path) as fp:
controller.deserialize(json.load(fp))
async def start(self):
self.controllers.load_all()
self.load_serialized_state()
self._connect_base_signals()
self.start_controllers()
def run(self):
self.base_model = self.make_model()
try:
self.controllers.load_all()
self.load_serialized_state()
self._connect_base_signals()
self.start_controllers()
self.aio_loop.create_task(self.start())
self.aio_loop.run_forever()
finally:
self.aio_loop.run_until_complete(

View File

@ -251,6 +251,7 @@ class TuiApplication(Application):
extend_dec_special_charmap()
self.toggle_rich()
self.urwid_loop.start()
self.select_initial_screen(self.initial_controller_index())
def initial_controller_index(self):
if not self.updated:
@ -266,14 +267,16 @@ class TuiApplication(Application):
controller_index = i
return controller_index
async def start(self, start_urwid=True):
await super().start()
if start_urwid:
self.start_urwid()
def run(self):
if self.opts.scripts:
self.run_scripts(self.opts.scripts)
self.aio_loop.call_soon(self.start_urwid)
self.aio_loop.call_soon(
lambda: self.select_initial_screen(
self.initial_controller_index()))
try:
super().run()
finally:
self.urwid_loop.stop()
if self.urwid_loop is not None:
self.urwid_loop.stop()