Open ITAYC0HEN opened 5 years ago
Related: https://github.com/radare/radare2/pull/13622 (to not clutter the output as much)
We have CutterCore::message()
https://github.com/radareorg/cutter/blob/master/src/core/Cutter.cpp#L722
So you can just use cutter.message()
instead of print()
.
But people use print, which is okay, should be redirected to Cutter.Message
And there are more ways to generate output to STDOUT and STDERR in python (and any other thingies), not only prints. Even when python throws exception I'd expect it to be on Console widget and not on the executing Terminal (which not always exists)
Python and plugins are initialized before MainWindow. So we have to change the order.
We can have some kind of buffer for output received before the MainWindow has been started. There might be something interesting in it, even without Python Plugins.
I agree that this should be the default. Existing interactive disassembler platforms already behave this way, so now all of your users will expect Cutter to behave the same way whether you like it or not 😅
Might be best not to overthink this. IDA has a pretty straightforward implementation that you can draw from for Cutter.
They hook the interpreter's stdout/stderr stream with a simple proxy object:
The proxy simply passes along any file descriptor writes to idaapi.msg()
, eg cutter.message()
:
@gaasedelen sounds great! Want to have a look and try solve it? Actually, maybe this can be fixed globally somehow for the whole application https://github.com/radareorg/cutter/issues/966
Yes, this should not be done in python. There are ways to replace/redirect the actual stderr/stdout fds.
Working on this issue in PR #1821. If you have any additional suggestions or recommendations based on your experience please add them there.
The pull request https://github.com/radareorg/cutter/pull/1821 is not merged but we still did not solve the issue for python printings
Python (Well, 3 at least) just writes to the standard stdio fds, so if you redirect them, it should redirect its output as well (pytest does that for example). But note that Python checks whether the standard streams are a terminal or not to configure buffering, so you might want to add startup code to reconfigure them as needed.
Though under /SUBSYSTEM:WINDOWS
it does set them to None
.
This boils down to init order. At least on Windows, Python has a special hack when stdio is a console to use WriteConsoleW
instead so that it handles unicode (AKA winconsoleio
). As such if you initialize Python before setting up output redirection, it will initialize to using that. You can reinitialize the Python stdio like this (Python 3, it's a bit more complicated in 2 as far as I recall):
sys.stdin = open(0, "r", closefd=False)
sys.stdout = open(1, "w", closefd=False)
sys.stderr = open(2, "w", closefd=False)
(Or from C PyFile_FromFd
, PySys_SetObject
)
Which can be done before calling Python again after setting up output redirection. Alternatively, delay Python initialize until after setting up output redirection.
It's also worth considering the buffering
mode set for the stdio streams in Python.
Also, Python 3.8 new initialization API also allows some control over this: https://docs.python.org/3/c-api/init_config.html
P.S. I'm still wondering about the weird behavior when running from a console, which causes output to the console to freeze once setting up output redirection but then somehow continue after closing cutter... that's weird...
Is your feature request related to a problem? Please describe.
Currently, when Plugin author uses
print("hello, world")
, the output would be executed on the terminal which was executing Cutter (on windows usually there won't be a terminal for this).This is unexpected behavior since we have a Console Widget
Describe the solution you'd like I want STDOUT to be redirected to the Console widget. In general, but specifically here for Python Plugins.
Additional context
related issue: #966