BlockingIOError Still Seen in v0.10.7
jetblackrx89 opened this issue · comments
ChromaTerm version
ct 0.10.7
Terminal
iTerm 2
What's happening?
Seem like the commit for issue #93 either got backed out or wasn't properly committed. I am seeing the same BlockingIOError on pretty much any telnet session to any Cisco router on a corporate network due to the fact that the output obviously isn't immediate but rather delayed by a couple hundred milliseconds.
I manually imported the patched "__main__.py" from the commit listed at the end of that bug and it seems to work fine. If telnet is slow, it adds an extremely minor delay in output so outputs can be color formatted properly. When running commands locally on my own computer, the output is immediate. I think the fix is working properly, so can it be committed to the main branch?
The fix (e330cb0) is already applied; It was never removed, although it was refactored a bit.
ChromaTerm/chromaterm/__main__.py
Lines 285 to 289 in 8792122
Can you run pip3 install --force-reinstall chromaterm
then paste the traceback when the error is shown? And how do you invoke ChromaTerm (e.g. ct ssh host
, ssh host | ct
, or terminal-wide highlighting)?
Thanks for the response. As soon as I run pip3 install --force-reinstall chromaterm
the issue returns. Traceback seen:
File "/usr/local/bin/ct", line 8, in <module>
sys.exit(main())
File "/usr/local/lib/python3.10/site-packages/chromaterm/__main__.py", line 499, in main
process_input(config, data_fd, forward_fd, max_wait)
File "/usr/local/lib/python3.10/site-packages/chromaterm/__main__.py", line 332, in process_input
sys.stdout.flush()
BlockingIOError: [Errno 35] write could not complete without blocking
I am running CT via adding a new "profile" to iTerm 2 to intercept all telnet:// URL's with the command /usr/local/bin/telnet_chromaterm $$HOST$$ $$PORT$$
. I think I did it this way because iTerm 2 doesn't like piped outputs in the "profiles" > "command" setting. "telnet_chromaterm" is a very basic bash script I wrote that in turn does:
#!/bin/tcsh
/usr/local/bin/telnet $1 $2 | /usr/local/bin/ct
I was able to recreate this issue using a pubic route server.
ChromaTerm is settings stdout
to blocking
mode (as intended), but the telnet
client is setting the stdout
back to non-blocking
after logging in, which is causing this issue.
For the time being, you can change your script to use /usr/local/bin/ct /usr/local/bin/telnet $1 $2
which will provide telnet
with a pseudo TTY, so it wouldn't change the blocking mode of the real stdout
.
Thank you so much. I followed your suggestion and modified the wrapper bash script I made per your suggestion, and it's working fine now.
Unfortunately, fixing this is not feasible due to how some programs behave, so you should let ChromaTerm spawn your program (i.e. as per the suggestion above).
Using pipes will make it so a program can escape the redirection and gain direct access to stdout
(see #80 for an example). As such, some programs will modify the properties of stdout
, like telnet
. The workaround would be to periodically override them, which might cause unintended effects to the program. And even then, the program can simply reapply their changes at any point.
I could wrap various parts of the code with error handling, but because of the nature of writing to a non-blocking
file descriptor, I wouldn't know how much of the data was written out before the error was encountered, so we'd either have to print it twice or just move on. Either way, the output would be invalid. There's also the possibility of using select.select
to ensure the stdout
is ready to be written to, but that would incur a performance penalty because I'd have to runs this check before every single write call, of which there are many.
I'd rather that people avoid pipes when dealing with intricate programs that attempt to escape piping or modify the properties of stdout
. Let ct
spawn your program.