Skip to content

Commit 442d270

Browse files
committed
fix shutdown
1 parent 0dd4664 commit 442d270

File tree

4 files changed

+20
-82
lines changed

4 files changed

+20
-82
lines changed

src/textual/_xterm_parser.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,12 @@ def parse(self, on_token: TokenCallback) -> Generator[Awaitable, str, None]:
6565

6666
while not self.is_eof:
6767
character = yield read1()
68+
log.debug("character=%r", character)
6869
if character == ESC and ((yield self.peek_buffer()) or more_data()):
6970
sequence: str = character
7071
while True:
7172
sequence += yield read1()
72-
log.debug(f"sequence={sequence!r}")
73+
log.debug(f"sequence=%r", sequence)
7374
keys = get_ansi_sequence(sequence, None)
7475
if keys is not None:
7576
for key in keys:

src/textual/app.py

Lines changed: 12 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,10 @@ async def _process_messages(self) -> None:
113113
except Exception:
114114
log.exception("error starting application mode")
115115
raise
116-
try:
117-
await super().process_messages()
118-
finally:
119-
try:
120-
driver.stop_application_mode()
121-
finally:
122-
loop.remove_signal_handler(signal.SIGINT)
116+
await super().process_messages()
117+
118+
await self.view.close_messages()
119+
driver.stop_application_mode()
123120

124121
async def add(self, child: MessagePump) -> None:
125122
self.children.add(child)
@@ -132,45 +129,16 @@ async def remove(self, child: MessagePump) -> None:
132129
async def shutdown(self):
133130
driver = self._driver
134131
driver.disable_input()
135-
136-
async def shutdown_procedure() -> None:
137-
log.debug("1")
138-
await self.stop_messages()
139-
log.debug("2")
140-
await self.view.stop_messages()
141-
log.debug("3")
142-
log.debug("4")
143-
await self.remove(self.view)
144-
if self.children:
145-
log.debug("5")
146-
147-
async def close_all() -> None:
148-
for child in self.children:
149-
await child.close_messages(wait=False)
150-
await asyncio.gather(*(child.task for child in self.children))
151-
152-
try:
153-
await asyncio.wait_for(close_all(), timeout=5)
154-
log.debug("6")
155-
except asyncio.TimeoutError as error:
156-
raise ShutdownError("Timeout closing messages pump(s)") from None
157-
log.debug("7")
158-
159-
log.debug("8")
160-
await self.view.close_messages()
161-
log.debug("9")
162-
await self.close_messages()
163-
log.debug("10")
164-
165-
await asyncio.create_task(shutdown_procedure())
132+
await self.close_messages()
166133

167134
def refresh(self) -> None:
168-
console = self.console
169-
try:
170-
with console:
171-
console.print(Screen(Control.home(), self.view, Control.home()))
172-
except Exception:
173-
log.exception("refresh failed")
135+
if not self._closed:
136+
console = self.console
137+
try:
138+
with console:
139+
console.print(Screen(Control.home(), self.view, Control.home()))
140+
except Exception:
141+
log.exception("refresh failed")
174142

175143
async def on_event(self, event: events.Event) -> None:
176144
if isinstance(event, events.Key):

src/textual/events.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class EventType(Enum):
5050
CUSTOM = 1000
5151

5252

53+
@rich_repr
5354
class Event(Message):
5455
type: ClassVar[EventType]
5556

src/textual/message_pump.py

Lines changed: 5 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ def __init__(self, queue_size: int = 10, parent: MessagePump | None = None) -> N
2828
self._pending_message: Message | None = None
2929
self._task: Task | None = None
3030
self._child_tasks: set[Task] = set()
31-
self._queue_empty_event = Event()
3231

3332
@property
3433
def task(self) -> Task:
@@ -111,34 +110,16 @@ def set_interval(
111110
asyncio.get_event_loop().create_task(timer.run())
112111
return timer
113112

114-
async def stop_messages(self) -> None:
115-
if not self._closing:
116-
await self.post_message(events.NoneEvent(self))
117-
self._closing = True
118-
return
119-
if not (self._closing or self._closed):
120-
self._queue_empty_event.clear()
121-
await self.post_message(events.NoneEvent(self))
122-
self._closing = True
123-
await self._queue_empty_event.wait()
124-
self._queue_empty_event.clear()
125-
126113
async def close_messages(self, wait: bool = True) -> None:
127114
"""Close message queue, and optionally wait for queue to finish processing."""
128115
if self._closed:
129116
return
130-
log.debug("close_messages %r wait=%r", self, wait)
117+
131118
self._closing = True
132-
log.debug("close 1 %r", self)
119+
await self._message_queue.put(None)
120+
133121
for task in self._child_tasks:
134122
task.cancel()
135-
log.debug("close 2 %r", self)
136-
await self._message_queue.put(None)
137-
log.debug("close 3 %r", self)
138-
if wait and self._task is not None:
139-
await self._task
140-
self._task = None
141-
log.debug("close 4 %r", self)
142123

143124
def start_messages(self) -> None:
144125
self._task = asyncio.create_task(self.process_messages())
@@ -149,15 +130,14 @@ async def process_messages(self) -> None:
149130
try:
150131
message = await self.get_message()
151132
except MessagePumpClosed:
152-
log.debug("CLOSED %r", self)
153133
break
154134
except Exception as error:
155135
log.exception("error in get_message()")
156136
raise error from None
157137

158138
log.debug("%r -> %r", message, self)
159139
# Combine any pending messages that may supersede this one
160-
while True:
140+
while not (self._closed or self._closing):
161141
pending = self.peek_message()
162142
if pending is None or not message.can_batch(pending):
163143
break
@@ -172,21 +152,14 @@ async def process_messages(self) -> None:
172152
log.exception("error in dispatch_message")
173153
raise
174154
finally:
175-
log.debug("a")
176155
if self._message_queue.empty():
177-
log.debug("b")
178-
self._queue_empty_event.set()
179156
if not self._closed:
180157
idle_handler = getattr(self, "on_idle", None)
181-
log.debug("c %r", idle_handler)
182158
if idle_handler is not None and not self._closed:
183-
log.debug("d")
184159
await idle_handler(events.Idle(self))
185-
log.debug("e")
186-
self._queue_empty_event.set()
160+
log.debug("CLOSED %r", self)
187161

188162
async def dispatch_message(self, message: Message) -> bool | None:
189-
log.debug("dispatch_message %r", message)
190163
if isinstance(message, events.Event):
191164
await self.on_event(message)
192165
else:
@@ -196,7 +169,6 @@ async def dispatch_message(self, message: Message) -> bool | None:
196169
async def on_event(self, event: events.Event) -> None:
197170
method_name = f"on_{event.name}"
198171
dispatch_function: MessageHandler = getattr(self, method_name, None)
199-
log.debug("dispatching to %r", dispatch_function)
200172
if dispatch_function is not None:
201173
await dispatch_function(event)
202174
if event.bubble and self._parent and not event._stop_propagaton:
@@ -217,15 +189,11 @@ def post_message_no_wait(self, message: Message) -> bool:
217189
return True
218190

219191
async def post_message(self, message: Message) -> bool:
220-
log.debug("%r post_message 1", self)
221192
if self._closing or self._closed:
222193
return False
223-
log.debug("%r post_message 2", self)
224194
if not self.check_message_enabled(message):
225195
return True
226-
log.debug("%r post_message 3", self)
227196
await self._message_queue.put(message)
228-
log.debug("%r post_message 4", self)
229197
return True
230198

231199
async def post_message_from_child(self, message: Message) -> bool:

0 commit comments

Comments
 (0)