-
-
Notifications
You must be signed in to change notification settings - Fork 375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Capture emulator stdout
during startup
#1687
Conversation
16c45fe
to
ca860db
Compare
stdout
during startupstdout
during startup
4549cb9
to
64023bf
Compare
- Capture Android emulator output during its startup
64023bf
to
6ea731a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broadly makes sense (I think...); a couple of nitpicks inline, but on the whole this looks like a good refactoring of a complex part of the streaming code.
The only other issue I noticed is a weird one - the code clearly has 100% coverage, but I can't see how the capture_output = False
case is being exercised. I'm guessing it's being tested implicitly by another test somewhere, but given it's at the core of how this works, it would be worth having an explicit test.
To make sure I'm understanding what is going on here - the key to the problem is that the old Popen usage wasn't ever invoking readline()
, which apparently causes Windows to lock up and not produce output. The code now always uses a background thread to poll and collect stdout (not just for the stream_output()
case). The Android usage previously only used communicate()
to gather output in the case of an error, and otherwise ignored output. The new implementation does continuous readline()
polling to get output as it is generated, which should (hopefully 🤞) unblock Windows.
Have I got that right?
@@ -1412,6 +1410,8 @@ def start_emulator( | |||
self.tools.logger.info(general_error_msg) | |||
|
|||
raise | |||
finally: | |||
emulator_streamer.stop_flag.set() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be inclined to wrap this as a streamer.stop()
method (or similar), rather than reaching into the internal implementation so if we ever have more complex "kill the streamer" logic, we don't miss anything that is required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense; although, I'm inclined to call it streamer.request_stop()
because readline()
is blocking and as such, we can't guarantee setting this flag will actually ever cause the thread to exit (....you know, if its stuck in readline()
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure the exact name doesn't really concern me, it's more the conceptual wrapping of the behavior, rather than reaching into internals. Also stop()
could easily be confused for a method on the core thread API (it doesn't AFAICT, but stop()
would be an obvious conceptual match for run()
... but it won't behave that way).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RE: stopping threads
I always loved this blog post from raymond chen....although, he seemingly removed it...
:param label: A description of the content being streamed; used for to provide | ||
context in logging messages. | ||
:param popen_process: A running Popen process with output to print | ||
:param capture_output: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing a description here
Would you consider the
Right....the theory is if we read More broadly, this provides the option of creating a |
Ah - that was the case I was missing. It's relying on the default value of the argument.
👍
Yeah - that's a nice API addition. Not sure if we'll have any use for it, but it's a nice club to have in the bag just in case, and the rest of the refactoring around adding that API are all nice improvements as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All looks good... now to cross our fingers and hope it actually fixes the windows emulator lockup problem 🤞
Changes
stdout
resolves the issuePopenOutputStreamer
for encapsulating the output streamThread
and adds the ability to capture instead of print outputSubprocess.stream_output_non_blocking()
alongside the existingSubprocess.steam_output()
to facilitate callers streaming (and conditionally capturing output) while doing other tasksPR Checklist: