-
Notifications
You must be signed in to change notification settings - Fork 16
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
How should Proc::Async.new, run and shell call cmd.exe? #20
How should Proc::Async.new, run and shell call cmd.exe? #20
Comments
How command line processing on Windows worksDo read this awesome writeup of how commandline processing works on Windows. Also don't miss this bugreport that already has a proposal of how to handle this in Perl 6. Windows does not have the concept of an ARGV array. At the API level there is only one single string that is passed. There is a convention (CommandLineToArgv() implements that) of how a string array is converted to a single string and back. With rare exceptions all programs adhere to this convention. The most prominent exception is When calling an The CommandLineToArgv() quoting (CLTA)If the argument contains The cmd quoting
|
Five possible usage scenariosIn decreasing order of commonness.
Number 4. and 5. won't happen in any normal usage scenarios. What others dolibuv quotes arguments compatible to node exposes a javas |
Initial proposalA good API should:
Proc::Async idea 1Add a new enum
Proc::Async idea 2Add a new flag to the
run idea
shell idea
|
I like the java way of doing it (+ a flag to disable it if they don't do that) because it doesn't require the programmer to have as much of an understanding of e.g. Windows to write platform-independent code. Not thrilled about the idea of speccing some potentially complex and heuristic-based logic though. The |
(Edited to simplify.) This comment is my 2c on the API / paintwork, either reflecting my confusion or, if I'm not confused, reflecting my concerns and attempts to reduce confusion:
I named the overall
Putting these together, our doc might say something like:
|
Here is how I intended the respective parameters to influence processing:
Now on to your proposal.
|
@ugexe I fully agree with all of your points. Sadly I haven't been able to come up with a solution that fits all bills. I'm open for other suggestions! |
Some links I found during my research of this issue that might be useful. A key comment in a libuv issue: libuv/libuv#2627 (comment) Two SOs that may only be useful because they're so monumental and scary that it emphasizes the need for a "Give enough control to the user to call any program the way he wants." escape hatch: https://stackoverflow.com/questions/6828751/batch-character-escaping and https://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts A link to fellow PL folk (Julia) in the process of figuring out related issues: JuliaLang/julia#34111 |
@patrickbkr You have it about right for my paintjob. To sort the one point of confusion, my intent was that Is your |
Exactly. |
Thanks for following up in that reddit @patrickbkr. I suspect you got nothing at all out of it but I wanted to try. Also, I promised folk in my reddit post I'd follow up today if no one else had replied to them. There is one remaining as-yet-unanswered follow up to a comment you made @patrickbkr, and one other that didn't get any response so I said I'd post it here:
|
@raiph As far as I know we do not have any API to directly pass a string. Because of that it's sometimes impossible to work around this issue - there is no API to fall back to. |
@patrickbkr To try to be clear, I presumed there was no API to fall back on at the moment. But I also thought that your proposal, which I imagine is what the poster was asking about, was to provide an API that, among other cases, covered this passthru case so that a user could indeed do whatever they wanted provided they called the code they needed to call. I thought this was perhaps (probably?) available via the |
@raiph Yes, I was talking about our current situation. The new API will hopefully provide the means to be able to just pass a single string that won't be processed (via the |
Thinking about this some more. I'm a bit uneasy about my no. 5 use case.
I don't see when one would actually need such double quoting. But that's exactly what the Microsoft blog promotes. So I guess I miss the point there. It would be a bad idea to just ignore that use case then. |
My two API ideas each have a tradeoff: Idea 1: We are limited to three given built in quoting systems that are provided. Given you need a different one, you have to set it to Idea 2: This proposal uses separate functions. Of the top off my head I can't remember any other place in the Raku setting where there are such dependent functions. i. e. One needs to know about the existence of the I currently lean toward Idea 1. We can add other options later when actual use cases show up. And it's still possible to turn automatic quoting off entirely and do it all by yourself. |
It seems like you're saying that you don't get why that MS person recommend this, but you nevertheless think they must surely have a point, perhaps even a good one. As another data point, let me quote a 2017 perlmonks post:
afoken's profile page includes plenty of evidence they're to be taken seriously on this topic. More importantly, their comment has "Reputation: 22 (no significant downvotes)?" and no rebuttal. For a comment like it, that voting/reply/rebuttal status on perlmonks speaks very loudly. I grant that it's probably written from the perspective of someone whose main focus is perl but, to the degree there is any conflict between the perspective the MS writer provides, and the one afoken provides, but you must make simplifying presumptions (even if it's the presumption "I can't afford to make such-and-such a presumption"), I'd recommend erring on the side of being consistent with afoken's perspective, rather than trusting the perspective of a random MS blog poster. |
More thoughts: There is no reliable way to escape parameters for use with CMD. CMD splits its argument string on space (and So I once again change my mind and now favour my Idea No. 2: Provide a toggle to turn off argument quoting on Windows. But I wouldn't provide separate quoting subs anymore. The CLTR quoting sub is not needed as that quoting is already active by default. A CMD quoting sub should be omitted because it can't be made to work right. This is pretty much what node.js decided to do. I have a basic implementation of this running. |
I have looked around a bit. It seems there really is no sensible way to make Java cooperate. So I'll just fall back to using Javas built in logic when running on the JVM. |
Together with a change in rakudo this fixes Raku/problem-solving#20.
I have created the above two draft PRs. They implement a Feedback welcome! |
Together with a change in rakudo this fixes Raku/problem-solving#20.
Above is another PR for NQP that adapts the JS backend to the proposed solution. |
I think there is nothing I can do to push this any further. So this ticket is now blocking on feedback. |
I wonder if its worth having a test that checks the command line arguments come out correct via something like Do you happen to know if we can get the escaped command the JVM would run in such a way that we could set I wanted to modify zefs AppVeyor to use a path with a space to see what would happen, but I have not gotten around to that. However -- this all appears sane to me. |
If I understand your comment correctly you'd like to have tests to check the argument string that is handed to Alternatively we could expose the As far as I know the JVM has no way of retrieving the thing it sent out. I wrote a set of very platform specific tests on Windows using a custom bat script that dumps its args and a native executable doing the same. But that only checks that the args we expect arrive in the called application (so already deserialized). With a bit of bodging I might be able to create a native executable that directly prints the single argument string it is passed. One could then check for that. Not sure how good an idea it is to have the test suite create native executables for testing though. None of the above ideas are particularly pretty. |
Edit: it does make sense to be able to run .command back through run, in which case the escaped .command would not do the right thing. So definitively scratch that.
|
Why not run a raku script to dump those arguments? I'd think our handling of incoming arguments is pretty solid by now. |
@niner: I can do that (I can then even reuse the tests I already have). But when doing this naively I only test what arguments arrive in the target process (the already deserialized array of command arguments), not how the single quoted argument string looks like. To actually look at that quoted argument string that was actually passed to |
Sure, NativeCall seems like the right tool for the job |
Tests added to a roast PR. |
Documentation added in a doc PR. I think that's all I can do. So this ticket now needs feedback to progress further. |
I read the manual for the problem-solving repo again and realized a PR with a solution description is necessary. So here it is: Windows-process-argument-quoting.md |
Together with a change in rakudo this fixes Raku/problem-solving#20.
Solution for #20: Windows process argument quoting
Together with a change in rakudo this fixes Raku/problem-solving#20.
Together with a change in rakudo this fixes Raku/problem-solving#20.
The solution document was approved and merged. So this issue is now solved. The implementation will be merged shortly. |
On Windows it is not possible to call
cmd.exe
with complex arguments. Calling.bat
files is affected as well. Rakudo bug r#2005 also reports this.Short problem description
On Windows the API to start programs (CreateProcess) does not take an array, but a single string. There is a convention nearly all programs adhere to of how to turn an array of arguments into a single string (a well defined quoting). This convention is what rakudo currently implements (via libuv, which does the actual quoting).
Not all programs adhere to this convention. Most prominently
cmd.exe
and as a result.bat
scripts.When trying to call a
.bat
file rakudo applies the usual quoting to the commandline arguments and as a result makes it impossible to pass some arguments.Perl 6 functionality affected:
Proc::Async
,shell
andrun
.How could the API look that in addition to the current behaviour also allows to call
cmd.exe
and any other program not adhering to the commandline quoting convention?The text was updated successfully, but these errors were encountered: