-
Notifications
You must be signed in to change notification settings - Fork 55
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
Pebble exec, when in enforced interactive mode, is prone to losing some of the command output #306
Comments
Thanks for the report, @dmitry-lyfar. Just for the record, the three different cases I've seen are as follows (with the first being the most common):
|
@benhoyt This is the relevant issue from LXD that I mentioned to you before: canonical/lxd#12285. Also, please see this comment on the GetPollRevents: canonical/lxd#12210 (comment). |
Extending the list of the known exit codes (no output):
|
@benhoyt @IronCore864 I think I narrowed the issue to a POC that potentially solves it. The root problem is that by using Pebble starts two go routines that mirror stdin/stdout from the client.
So, on:
the go routine from p. 2 reads the input entirely, writes it to the master, sees that there is an EOF (actually, "end" from the websocket) and closes the master descriptor. The go routine from p.1 is still working and reading the output from the master descriptor to mirror it to the websocket. Given that it has just been closed, it detects POLINVAL and exists even if there is data to read. This is not a problem when the interactive mode is set automatically due to the command being run in the terminal as the reading go routine (p.2) would only return when a user terminates the process somehow. The suggested solution is simple -- write EOF to the pty to indicate the end of stdin to the process. This way the examples using See the POC #466. |
This is a nice find and fix, thanks a lot @dmitry-lyfar! I'll look at the change a bit more closely in context in the next few days. It certainly seems to work nicely at first blush. |
Thanks @dmitry-lyfar for the diagnosis and the PoC. Before this, I had been trying to fix it using various methods, including porting the fix from the LXD PR you mentioned, but without success. After reading this PoC it came to me that the close of the master descriptor here is premature; it will be closed in the afterClosers. I tested it with long inputs like the |
Once again, much appreciated, @dmitry-lyfar. |
If one enforces the pebble exec interactive mode when executing a command and stdin returns EOF sooner than reading from the commands stdout ends, it may result in some output lost. Consider:
In both cases, the command's output will either be nonexistent or partial. This is likely due to the client closing the websocket connection with the server (
/v1/tasks/<task-id>/websocket/stdio
) before the command's stdout is fully read. In the interactive mode,stdio
websocket is used to redirect both stdin and stdout, hence, if the client's stdin go routine sends the end message to the websocket server it affects the routine reading stdout (see the line 68):pebble/internals/wsutil/wsutil.go
Lines 54 to 70 in 6134298
If sending the end message is delayed until the stdout routine reads all the produced output, it resolves the issue.
The text was updated successfully, but these errors were encountered: