Warnings being printed after input control is returned to `cmd.exe`
Although this bug has been spotted on outdated versions and a platform that is no longer supported, I still decided to write about it, because it may well still exist and indicate certain problems with the async code. Someone else needs to check it, since I don't have the opportunity to do it yet.
Problem
Assume having a Rust environment with tool management conflict(s) between Cargo and Rustup, which results in the well-known warning: tool is already installed. So, when a version specified in ${RUSTUP_UPDATE_ROOT}/rustup/release-stable.toml is distinct and I run rustup self update, then after downloading and installing it these warnings will be output literally into the command prompt. Moreover, this also sometimes happens not immediately, but literally a few seconds later. To me, this pretty suggests some kind of multithreading issue.
And once I noticed the same bug on another command: rustup toolchain install 1.77-gnu 1.77-i686 1.77-i686-gnu:
Configuration
Rustup versions tested: 1.27.1, 1.27.1+381 (03b7c56bf 2024-07-30) Operating system: Windows 7 Ultimate (Service Pack 1) x64
Additional notes
- Setting the environment variable
RUSTUP_IO_THREADS=1doesn't affect the observed behavior. - I tested version 1.27.1+381 because 03b7c56bf0b4228977257810218b963b7246cf62 is the last revision that can be built with Rust 1.77.2 and run on Windows 7 - I deliberately ran
git bisectto find this out. It's worth noting that the bug is also present there, but in addition the text can no longer be colored incmd.exestarting with commit 509714deb4b8bc5be7e38e2f3779ed4e2b704177, which is shown on the first screenshot as well.
@cher-nov Thanks for the report.
I think that is unfortunate but reasonable given that the outcome of mixed stdout/stderr output is not guaranteed. In your particular case, the warn: line goes to stderr and the installed line goes to stdout, and it seems that the final stderr line took some time to be printed out (it should actually precede the installed line if I'm not mistaken) so that the command prompt took the lead. Thus, this looks more like a problematic interpretation of the output rather than an actual functional bug, as we don't have any constraint other than the execution flow to ensure the ordering of such output lines 🤔
I'm not a Windows expert, but does switching to anything other than conhost/cmd help with this?
In your particular case, the
warn:line goes to stderr and theinstalledline goes to stdout, and it seems that the final stderr line took some time to be printed out
I think it's worth noting just in case that redirecting stderr to stdout doesn't help.
I'm not a Windows expert, but does switching to anything other than conhost/cmd help with this?
Yep, this bug does not occur e.g. in Git Bash from git version 2.45.2.windows.1.
But the thing is that Windows Console is still a standard Windows component, even in Windows 11.
(it should actually precede the
installedline if I'm not mistaken)
Looks like not - see the terminal screenshot without the bug above.
I think that is unfortunate but reasonable given that the outcome of mixed stdout/stderr output is not guaranteed.
Isn't it? I've never seen anything like this in my life, even though I had to rely on alternating stdout and stderr output in my Python3 scripts...
as we don't have any constraint other than the execution flow to ensure the ordering of such output lines 🤔
...but if you mean multithreading, then of course it is.
so that the command prompt took the lead.
I did a bit of reading through the rustup code and here's what I think is actually going on here:
- A user launches rustup. It checks for an update and downloads it.
- It then launches an updated version in background to install proxies or whatever. This new process will also show the warning, as you can see from the changes in its appearance on the screenshots I posted.
- The original process then terminates without waiting for the child one to complete. This causes the input to be returned to the user and the prompt to appear.
- The child process terminates, after displaying a warning when no one was expecting it anymore.
Thus, this looks more like a problematic interpretation of the output rather than an actual functional bug
Either way, it's still confusing. Otherwise, I just wouldn't have created this issue. 😎 Could you please add a label?
When updating the new exe needs to remove the old exe. On Windows this can only be done once the old exe has exited, which also means that control has been returned to the shell (which then prints the prompt). So if the new exe prints after that then it's going to have the results you see here.
Ideally what should happen is that we do as much of the setup process as possible while keeping the old exe running. Then deleting the old exe would be the final step and done after the old exe exits. This would however mean that we can't print a warning if deleting the exe fails for some reason.