fix: Improve non-blocking output reading in TerminalCog for active processes
This commit is contained in:
parent
07cd5d9acf
commit
e7719406bf
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user