Fix another crash on shutdown.

Mostly caused by a stupid bug in ProjectProcess.handle_close()...
looper
Ben Niemann 5 years ago
parent 42947bb85b
commit 77e0805b29
  1. 13
      noisicaa/core/ipc.py
  2. 16
      noisicaa/music/player.py
  3. 12
      noisicaa/music/project_process.py
  4. 8
      noisicaa/ui/editor_app.py

@ -37,7 +37,10 @@ from . import stats
logger = logging.getLogger(__name__)
class RemoteException(Exception): pass
class RemoteException(Exception):
def __init__(self, server_address, tb):
super().__init__("From server %s:\n%s" % (server_address, tb))
class Error(Exception): pass
class InvalidResponseError(Error): pass
class ConnectionClosed(Error): pass
@ -259,7 +262,7 @@ class ClientProtocol(asyncio.Protocol):
def connection_lost(self, exc):
self.closed_event.set()
logger.info("Client connection lost.")
logger.info("Client connection to %s lost.", self.stub.server_address)
self.response_queue.put_nowait(self.stub.CLOSE_SENTINEL)
def data_received(self, data):
@ -323,6 +326,10 @@ class Stub(object):
self._command_loop_cancelled = None
self._command_loop_task = None
@property
def server_address(self):
return self._server_address
@property
def connected(self):
return self._transport is not None
@ -413,7 +420,7 @@ class Stub(object):
elif response.startswith(b'OK:'):
return self.deserialize(response[3:])
elif response.startswith(b'EXC:'):
raise RemoteException(response[4:].decode('utf-8'))
raise RemoteException(self._server_address, response[4:].decode('utf-8'))
else:
raise InvalidResponseError(response)

@ -524,14 +524,6 @@ class Player(object):
async def cleanup(self):
logger.info("Cleaning up player instance %s..", self.id)
for listener in self.group_listeners.values():
listener.remove()
self.group_listeners.clear()
for buffer_source in self.track_buffer_sources.values():
buffer_source.close()
self.track_buffer_sources.clear()
if self.mutation_listener is not None:
self.mutation_listener.remove()
self.mutation_listener = None
@ -563,6 +555,14 @@ class Player(object):
self.proxy.cleanup()
self.proxy = None
for listener in self.group_listeners.values():
listener.remove()
self.group_listeners.clear()
for buffer_source in self.track_buffer_sources.values():
buffer_source.close()
self.track_buffer_sources.clear()
logger.info("Cleaning up player server...")
await self.server.cleanup()

@ -83,6 +83,12 @@ class Session(object):
listener.remove()
del self._players[player.id]
async def clear_players(self):
for player_id, (listener, player) in self._players.items():
await player.cleanup()
listener.remove()
self._players.clear()
def handle_pipeline_status(self, status):
if 'node_state' in status:
node_id, state = status['node_state']
@ -373,14 +379,16 @@ class ProjectProcessMixin(object):
await session.init_session_data(self.project.data_dir)
return self.project.id
def handle_close(self):
async def handle_close(self):
assert self.project is not None
tasks = []
for session in self.sessions.values():
tasks.append(self.event_loop.create_task(
session.callback_stub.call('PROJECT_CLOSED')))
asyncio.wait(tasks, loop=self.event_loop)
tasks.append(self.event_loop.create_task(
session.clear_players()))
await asyncio.wait(tasks, loop=self.event_loop)
self.project.close()
self.project = None

@ -177,6 +177,10 @@ class BaseEditorApp(QtWidgets.QApplication):
async def cleanup(self):
logger.info("Cleaning up.")
if self.project_registry is not None:
await self.project_registry.close_all()
self.project_registry = None
if self.audioproc_client is not None:
await self.audioproc_client.disconnect(shutdown=True)
await self.audioproc_client.cleanup()
@ -200,10 +204,6 @@ class BaseEditorApp(QtWidgets.QApplication):
self.sequencer.close()
self.sequencer = None
if self.project_registry is not None:
await self.project_registry.close_all()
self.project_registry = None
def quit(self, exit_code=0):
self.process.quit(exit_code)

Loading…
Cancel
Save