-
-
Notifications
You must be signed in to change notification settings - Fork 268
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
PipeTarget.ToDelegate blocks forever in StreamReader #185
Comments
I have a reliable reproduction available, but can't share it (proprietary code). If you try writing the logic using something apart from this StreamReader, I can test it from a branch. |
Does running the script directly as |
No. BUT I think I have a reproducible scenario. Create a cmd file with this content: start /min python This starts python.exe in the background, but the cmd file exits. CliWrap gets the exited event but gets blocked forever in reading the outputs. My expectation here is that CliWrap should complete the process as well, regardless of the status of the streams. |
Ok, thanks for the repro. I'll try to debug it after the holidays. |
Hi @vivainio. I tried reproducing it with the following setup.
var cmd = Cli.Wrap("test.cmd");
await foreach (var e in cmd.ListenAsync())
{
Console.WriteLine(e);
} Upon running the code, I was able to receive Note that I was able to observe the exact same behavior with I was able to avoid the blocking behavior by changing the script to this: start /B /min python The Finally, I was also able to reproduce the blocking behavior (without the using var process = new Process
{
StartInfo =
{
FileName = "test.cmd",
RedirectStandardOutput = true
}
};
process.Start();
var stdout = await process.StandardOutput.ReadToEndAsync();
await process.WaitForExitAsync(); Note that the above code only blocks if the standard output is redirected and read as shown above. Based on this, I can draw the conclusion that the spawned process somehow retains the standard output/error/input handles of the parent process. Which is what's preventing CliWrap (and also Also note that it's normal that a process exits before its standard streams are closed, this is not a special case in itself. I'm not sure what can be done in this scenario, as it seems like one of many quirks that Windows has with console processes. Is it viable for you to amend the script to use the |
@Tyrrrz I can't use /B switch as I need the output console. Since the underlying Process fires Exited event, which is never seen by CliWrap because of forever blocking output streams, I think a good solution is exposing the Exited even in CliWrap. The ListenAsyn() model could handily expose this as a new even type that is fired before ExitedCommandEvent. Too bad ExitedCommandEvent name is already taken as this is what it logically means. One more compatible way could maybe be adding an optional "emit process exit immediately on exit" flag on ListenAsync. I wouldn't something clunkier though, as long as I could hook into that raw event directly when it comes. |
How would that help if the execution would still block afterwards? |
When I'm in "ListenAsync" mode, I could bail out from the await foreach loop when I see that signal. I could then cancel the rest with CancellationToken (I think) |
Another thing you might try to do is to explicitly redirect ALL underlying streams inside your batch script. This way the handles shouldn't be inherited, I think. start /min python 0> nul 1> nul 2> nul This assumes you don't need the streams, of course. If you do (i.e., the user is expected to use the I found a related StackOverflow question with some extra context: https://stackoverflow.com/questions/36091748/how-do-i-use-the-start-command-without-inheriting-handles-in-the-child-process |
I had a similmar problem and in my mybatfile.cmd, I added an exit command in the last line and it solved my problem. |
After some deliberation on this, I decided to conclude that this behavior aligns with the design and all potential solutions on CliWrap's side are unfortunately too clunky to implement within the established model. On the consumer's side, these are the main solutions, depending on the use case:
|
Version
ver 3.5.0
Details
This is a spin off issue from: #85
Running a particular process ("cmd /c mybatfile.cmd") never finishes.
I have pinpointed this to this StreamReader reading in PipeTarget.cs:
Looks like this foreach loop never completes with this particular process.
I have a reliable reproduction, but I can't share the target process. For most other processes, this works correctly.
Steps to reproduce
The text was updated successfully, but these errors were encountered: