Skip to content
This repository has been archived by the owner on Nov 29, 2022. It is now read-only.

BlockingIOError Still Seen in v0.10.7 #102

Closed
jetblackrx89 opened this issue Oct 17, 2022 · 5 comments
Closed

BlockingIOError Still Seen in v0.10.7 #102

jetblackrx89 opened this issue Oct 17, 2022 · 5 comments
Labels
bug Something isn't working

Comments

@jetblackrx89
Copy link

jetblackrx89 commented Oct 17, 2022

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?

@jetblackrx89 jetblackrx89 added the bug Something isn't working label Oct 17, 2022
@hSaria
Copy link
Owner

hSaria commented Oct 17, 2022

The fix (e330cb0) is already applied; It was never removed, although it was refactored a bit.

# #93: Avoid BlockingIOError when output to non-blocking stdout is too fast
try:
getattr(os, 'set_blocking', lambda *_: None)(sys.stdout.fileno(), True)
except io.UnsupportedOperation:
pass

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)?

@jetblackrx89
Copy link
Author

jetblackrx89 commented Oct 17, 2022

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

@hSaria
Copy link
Owner

hSaria commented Oct 17, 2022

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.

@jetblackrx89
Copy link
Author

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.

@hSaria
Copy link
Owner

hSaria commented Oct 18, 2022

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.

@hSaria hSaria closed this as not planned Won't fix, can't repro, duplicate, stale Oct 18, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants