fix: Improve non-blocking output reading in TerminalCog for active processes

This commit is contained in:
Slipstream 2025-05-17 19:13:18 -06:00
parent 07cd5d9acf
commit e7719406bf
Signed by: slipstream
GPG Key ID: 13E498CE010AC6FD

View File

@ -345,50 +345,11 @@ class TerminalCog(commands.Cog, name="Terminal"):
updated = False
if self.active_process:
new_output_lines = []
interactive_prompt_detected = False
try:
# Read non-blockingly from stdout and stderr
while True:
stdout_line = self.active_process.stdout.readline()
stderr_line = self.active_process.stderr.readline()
if not stdout_line and not stderr_line:
break # No more output currently
if stdout_line:
line = stdout_line.strip()
new_output_lines.append(line)
updated = True
# Basic check for interactive prompts (can be improved)
if line.strip().endswith((':', '#', '$', '>')):
interactive_prompt_detected = True
if stderr_line:
line = f"STDERR: {stderr_line.strip()}"
new_output_lines.append(line)
updated = True
# Check stderr for prompts too, though less common
if stderr_line.strip().endswith((':', '#', '$', '>')):
interactive_prompt_detected = True
except Exception as e:
new_output_lines.append(f"Error reading process output: {e}")
updated = True
if new_output_lines:
self.output_history.extend(new_output_lines)
if self.active_process.poll() is not None: # Process has finished
return_code = self.active_process.returncode
# Read any final output
final_stdout, final_stderr = self.active_process.communicate()
if self.last_command: # Add the executed command to history
self.output_history.append(f"{self.current_cwd}> {self.last_command}")
self.last_command = None
if final_stdout: self.output_history.extend(final_stdout.strip().splitlines())
if final_stderr: self.output_history.extend([f"STDERR: {l}" for l in final_stderr.strip().splitlines()])
@ -398,7 +359,28 @@ class TerminalCog(commands.Cog, name="Terminal"):
if self.auto_update_task.is_running(): # Stop loop if it was running for this process
self.auto_update_task.stop()
updated = True
else: # Process is still running, check for new output without blocking
try:
# Read available output without blocking
stdout_output = self.active_process.stdout.read()
stderr_output = self.active_process.stderr.read()
if stdout_output:
self.output_history.extend(stdout_output.strip().splitlines())
updated = True
if stderr_output:
self.output_history.extend([f"STDERR: {l}" for l in stderr_output.strip().splitlines()])
updated = True
except io.UnsupportedOperation:
# This might happen if the stream is not seekable or non-blocking read is not supported
# In this case, we might just have to wait for the process to finish
pass # No update from this read attempt
except Exception as e:
self.output_history.append(f"Error reading process output: {e}")
updated = True
if updated or interaction: # if interaction, means it's a manual refresh, so always update
self.scroll_offset = max(0, len(self.output_history) - MAX_OUTPUT_LINES_PER_IMAGE)
await self._update_terminal_message(interaction)