Skip to content

Commit 808ba94

Browse files
f
1 parent 9ed9a9e commit 808ba94

2 files changed

Lines changed: 54 additions & 41 deletions

File tree

moler/io/raw/pty_process_unicode.py

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -118,24 +118,32 @@ def read(self, size: int) -> str:
118118
return data_str
119119

120120
except OSError as e:
121-
if e.errno == errno.EAGAIN:
121+
if e.errno == errno.EAGAIN: # Resource temporarily unavailable
122122
return "" # No data available, return empty string
123-
elif e.errno == errno.EIO:
123+
elif e.errno == errno.EIO: # Input/output error - process might be dead
124124
self.close(force=True)
125125
raise EOFError("End of file reached")
126126
else:
127127
raise
128128

129-
def close(self, force: bool = False) -> None:
130-
"""
131-
Close pty process.
132-
:param force: if True, forcefully kill the process
133-
:return: None
134-
"""
135-
if self._closed:
136-
return
137-
self._closed = True
129+
def _close_fds(self) -> None:
130+
"""Close file descriptors."""
131+
if self.fd >= 0:
132+
try:
133+
os.close(self.fd)
134+
except OSError:
135+
pass
136+
self.fd = -1
138137

138+
if self.slave_fd >= 0:
139+
try:
140+
os.close(self.slave_fd)
141+
except OSError:
142+
pass
143+
self.slave_fd = -1
144+
145+
def _terminate_process(self, force: bool) -> None:
146+
"""Terminate the child process."""
139147
# Try to terminate the process gracefully first
140148
if self.process and self.isalive():
141149
try:
@@ -155,20 +163,21 @@ def close(self, force: bool = False) -> None:
155163
except Exception as e:
156164
print(f"Error terminating process: {e}")
157165

158-
# Close file descriptors
159-
if self.fd >= 0:
160-
try:
161-
os.close(self.fd)
162-
except OSError:
163-
pass
164-
self.fd = -1
166+
def close(self, force: bool = False) -> None:
167+
"""
168+
Close pty process.
169+
:param force: if True, forcefully kill the process
170+
:return: None
171+
"""
172+
if self._closed:
173+
return
174+
self._closed = True
165175

166-
if self.slave_fd >= 0:
167-
try:
168-
os.close(self.slave_fd)
169-
except OSError:
170-
pass
171-
self.slave_fd = -1
176+
# Terminate the child process
177+
self._terminate_process(force=force)
178+
179+
# Close file descriptors
180+
self._close_fds()
172181

173182
def isalive(self) -> bool:
174183
"""

moler/observer_thread_wrapper.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,26 @@ def request_stop(self):
6262
if self._t:
6363
self._t = None
6464

65+
def _process_data_from_queue(self) -> None:
66+
"""Process data from queue."""
67+
try:
68+
data, timestamp = self._queue.get(True, self._timeout_for_get_from_queue)
69+
try:
70+
self.logger.log(level=TRACE, msg=f'notifying {self._observer}({repr(data)})')
71+
except ReferenceError:
72+
self._request_end.set() # self._observer is no more valid.
73+
try:
74+
if self._observer_self:
75+
self._observer(self._observer_self, data, timestamp)
76+
else:
77+
self._observer(data, timestamp)
78+
except ReferenceError:
79+
self._request_end.set() # self._observer is no more valid.
80+
except Exception as ex:
81+
self._handle_unexpected_error_from_observer(exception=ex, data=data, timestamp=timestamp)
82+
except queue.Empty:
83+
pass # No incoming data within self._timeout_for_get_from_queue
84+
6585
@tracked_thread.log_exit_exception
6686
def _loop_for_observer(self):
6787
"""
@@ -74,23 +94,7 @@ def _loop_for_observer(self):
7494
while not self._request_end.is_set():
7595
if next(heartbeat):
7696
logging.getLogger("moler_threads").debug("ALIVE")
77-
try:
78-
data, timestamp = self._queue.get(True, self._timeout_for_get_from_queue)
79-
try:
80-
self.logger.log(level=TRACE, msg=f'notifying {self._observer}({repr(data)})')
81-
except ReferenceError:
82-
self._request_end.set() # self._observer is no more valid.
83-
try:
84-
if self._observer_self:
85-
self._observer(self._observer_self, data, timestamp)
86-
else:
87-
self._observer(data, timestamp)
88-
except ReferenceError:
89-
self._request_end.set() # self._observer is no more valid.
90-
except Exception as ex:
91-
self._handle_unexpected_error_from_observer(exception=ex, data=data, timestamp=timestamp)
92-
except queue.Empty:
93-
pass # No incoming data within self._timeout_for_get_from_queue
97+
self._process_data_from_queue()
9498
self._observer = None
9599
self._observer_self = None
96100
logging.getLogger("moler_threads").debug("EXIT")

0 commit comments

Comments
 (0)