Repository: missionpinball/mpf
Issue: Crash when Shutting Down During Serice Mode

```
INFO : SwitchController : <<<<< switch: s_service_enter, State:1 >>>>>
INFO : ServiceController : Entered service mode. Resetting game if running. Resetting hardware interface now.
INFO : SwitchController : <<<<< switch: s_service_enter, State:0 >>>>>
^CINFO : Machine : Shutting down...
INFO : Machine : Shutting down...
INFO : Mode.attract : Mode Starting. Priority: 10
INFO : SwitchController : Active Switch|s_test_front
INFO : Mode.service : Mode Starting. Priority: 100000
ERROR : asyncio : Exception in callback EventManager.process_event_queue()
handle: <Handle EventManager.process_event_queue()>
Traceback (most recent call last):
  File "/usr/lib/python3.5/asyncio/events.py", line 125, in _run
    self._callback(*self._args)
  File "/data/home/jan/cloud/flipper/src/mpf/mpf/core/events.py", line 502, in process_event_queue
    **event[3])
  File "/data/home/jan/cloud/flipper/src/mpf/mpf/core/events.py", line 438, in _process_event
    result = handler.callback(**merged_kwargs)
  File "/data/home/jan/cloud/flipper/src/mpf/mpf/core/mode.py", line 218, in start
    **item.kwargs))
  File "/data/home/jan/cloud/flipper/src/mpf/mpf/core/config_player.py", line 177, in mode_start
    event_keys = self.register_player_events(config, mode, priority)
  File "/data/home/jan/cloud/flipper/src/mpf/mpf/config_players/plugin_player.py", line 47, in register_player_events
    self.bcp_client = self._get_bcp_client(config)
  File "/data/home/jan/cloud/flipper/src/mpf/mpf/config_players/plugin_player.py", line 30, in _get_bcp_client
    raise AssertionError("bcp connection {} not found".format(client_name))
AssertionError: bcp connection local_display not found
```

We need to properly stop all modes on shutdown to prevent things like this.


Changed files:
mpf/core/bcp/bcp_transport.py, mpf/core/async_mode.py, mpf/modes/service/code/service.py

diff --git a/mpf/core/async_mode.py b/mpf/core/async_mode.py
index 08f4a0b7c..7abf6460e 100644
--- a/mpf/core/async_mode.py
+++ b/mpf/core/async_mode.py
@@ -28,7 +28,10 @@ class AsyncMode(Mode, metaclass=abc.ABCMeta):
 
         Will raise exceptions from within task.
         """
-        future.result()
+        try:
+            future.result()
+        except asyncio.CancelledError:
+            pass
 
     def _stopped(self):
         """Cancel task."""
diff --git a/mpf/core/bcp/bcp_transport.py b/mpf/core/bcp/bcp_transport.py
index 1fdd71d99..8c8026c44 100644
--- a/mpf/core/bcp/bcp_transport.py
+++ b/mpf/core/bcp/bcp_transport.py
@@ -44,7 +44,10 @@ class BcpTransportManager:
 
         Will raise exceptions from within task.
         """
-        future.result()
+        try:
+            future.result()
+        except asyncio.CancelledError:
+            pass
 
     @asyncio.coroutine
     def _receive_loop(self, transport: BaseBcpClient):
diff --git a/mpf/modes/service/code/service.py b/mpf/modes/service/code/service.py
index f127529eb..fb7b3cc2d 100644
--- a/mpf/modes/service/code/service.py
+++ b/mpf/modes/service/code/service.py
@@ -58,12 +58,7 @@ down_events: list|str|sw_service_down_active
     def _start_main_menu(self):
         self.machine.service.start_service()
         self.machine.events.post("service_main_menu")
-        try:
-            yield from self._service_mode_main_menu()
-        except asyncio.CancelledError:  # pragma: no cover
-            # mode is stopping
-            self._service_mode_exit()
-            raise
+        yield from self._service_mode_main_menu()
 
         self._service_mode_exit()