Skip to content
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

Change win program resolution to match macOS/Linux #165

Merged
merged 6 commits into from
Jul 26, 2024

Conversation

lread
Copy link
Contributor

@lread lread commented Jul 25, 2024

After some careful study, I now understand the underlying behaviour of ProcessBuilder on Windows.

It has some nuances:

  • it resolves from the current dir before PATH (which CMD Shell does too - but PowerShell opted not to do for security reasons)
  • it only resolves a to a.exe
  • and has what seem to be bugs wrt to resolving when a directory working dir is specified

These oddities were sometimes leaking through to babashka process when run from Windows.

We now entirely take over the program resolution for Windows in our default :program-resolver which now matches the behaviour of PowerShell (with the exception of launching .ps1 files, we do not do that), macOS and Linux.

Note that the default :program-resolver is also employed for exec on all OSes. Because it matches macOS/Linux behaviour this does not present any problems.

Tests now thoroughly exercise program resolution via explicitly constructed scenarios instead of awkwardly relying on what happens to be on the PATH. See new test-resources dir README for some details.

Bb tasks adjusted accordingly to setup the PATH for tests. New dev:bb and dev:jvm tasks added to launch nREPLs with this same setup.

README is updated with new section on Program Resolution.

Closes #163
Closes #164

After [some careful study](https://github.com/lread/info-process-builder/blob/main/README.adoc#program-resolution),
I now understand the underlying behaviour of ProcessBuilder on Windows.

It has some nuances:
- it resolves from the current dir before PATH (which CMD Shell does too -
but PowerShell opted not to do for security reasons)
- it only resolves `a` to `a.exe`
- and has what seem to be bugs wrt to resolving when a `directory` working dir
is specified

These oddities were sometimes leaking through to babashka process when
run from Windows.

We now entirely take over the program resolution for Windows in our default
`:program-resolver` which now matches the behaviour of PowerShell (with
the exception of launching `.ps1` files, we do not do that), macOS and
Linux.

Note that the default `:program-resolver` is also employed for `exec` on
all OSes. Because it matches macOS/Linux behaviour this does not
present any problems.

Tests now thoroughly exercise program resolution via explicitly
constructed scenarios instead of awkwardly relying on what happens to
be on the PATH. See new test-resources dir README for some details.

Bb tasks adjusted accordingly to setup the `PATH` for tests.
New `dev:bb` and `dev:jvm` tasks added to launch nREPLs with this same setup.

README is updated with new section on Program Resolution.

Closes babashka#163
Closes babashka#164
@lread
Copy link
Contributor Author

lread commented Jul 25, 2024

Ready for your review, @borkdude; as usual, I am looking forward to your questions, comments, and feedback!

src/babashka/process.cljc Outdated Show resolved Hide resolved

:else
(fs/which program))]
(-> resolved fs/absolutize fs/normalize str)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this change necessary? It wasn't there before?

Copy link
Contributor Author

@lread lread Jul 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did absolutize before but only for relative programs with a dir.
(This was a change I made a while back f2c8d93, I am now wondering if it is absolutely necessary? 🥁)

It could be I am over-absolutizing here. The thing I liked about it is that it makes it very clear exactly what we are resolving to. I think I added normalize to make it clearer what we were absolutizing to, and that also made some test comparisons easier.

But I also see the value of not absolutizing/normalizing unless we need to. Can explore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer not processing the program name unless we have to as this may also affect the name of the program that is seen in exceptions etc. (same reason I don't prefer adding an extra cwd above)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable to me, I'll make the change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I committed the first suggested (because all the tests still worked, I felt it was permissible) but this other change fails a bunch of tests. To diagnose via CI I reversed the bb and JVM tests as the JVM tests give better error messages. Then when I changed the resolved return value to (str resolved) half the CI tests started working, except Windows. FWIW.

@lread
Copy link
Contributor Author

lread commented Jul 26, 2024

Thanks for the review!

Another thing to think about is that we have a single default program-resolver for

  • process on Windows
  • exec on all OSes

We could perhaps explore that their needs are different enough to warrant separate default implementations. For example, for exec on macos/Linux, a program-resolver could likely do less and fall through more.

Anyway before I make any further changes, I'll wait for your follow-up responses.

src/babashka/process.cljc Outdated Show resolved Hide resolved
@borkdude
Copy link
Contributor

We could perhaps explore that their needs are different enough to warrant separate default implementations.

Why actually? The need for this isn't entirely obvious to me.

@lread
Copy link
Contributor Author

lread commented Jul 26, 2024

We could perhaps explore that their needs are different enough to warrant separate default implementations.

Why actually? The need for this isn't entirely obvious to me.

I was thinking more of your desire to just pass through to the underlying JVM call when possible. I was focusing on Windows when modifying the :program-resolver. I did not carefully study exactly what resolving exec needs on macos/Linux. Maybe it needs exactly the same work to be done (or maybe it could do less and pass through more?) it's just something I did not look into very carefully for this PR.

@borkdude
Copy link
Contributor

I don't know, exec doesn't support :dir anyway so I don't think any bugs were introduced there at some point.

@borkdude
Copy link
Contributor

or do you mean, the exec-ing into a binary in the cwd?

@lread
Copy link
Contributor Author

lread commented Jul 26, 2024

Yeah, the same default :program-resolver we use for process on Windows is used for exec on all OSes. It works as is, but wondering out loud if they actually should be the same (and also not suggesting anything different).

@borkdude
Copy link
Contributor

I don't see a reason why they should be different but perhaps something will come to mind. Happy to address it in a future issue.

@lread
Copy link
Contributor Author

lread commented Jul 26, 2024

@borkdude, this commit should pass all tests when run from babashka/process, but I expect I'll need to tweak test expectations when running these process tests from babashka, so please don't merge yet. I'll follow up with a comment when I think things are all good.

Since we no longer always absolutize and normalize the resolved program,
revert a tweak I introduced in this PR.
@lread
Copy link
Contributor Author

lread commented Jul 26, 2024

Ok @borkdude, barring any more questions/concerns from you, I think you can merge now.

The absolutize is only necessary for ProcessBuilder on Windows, but should not be triggered for supported use of exec as :dir is not supported for exec.

@borkdude
Copy link
Contributor

Just one final remark, then we're good. I'm starting to see why you would want to split program-resolver for exec now (although, let's abstain until we see something going wrong)

@borkdude borkdude merged commit 264e950 into babashka:master Jul 26, 2024
17 checks passed
@borkdude
Copy link
Contributor

Thanks a lot for your thorough work!

@lread
Copy link
Contributor Author

lread commented Jul 26, 2024

You are always welcome @borkdude! Sorry, it took so long, but we now have a good understanding (and a reference) of how ProcessBuilder works on Windows!

@borkdude
Copy link
Contributor

No problemo!

lread added a commit to lread/process that referenced this pull request Jul 26, 2024
Can't tell you how I missed undoing a check against absolutized version
of an exe, but glad babashka CI didn't miss it!

Addendum for babashka#165
borkdude pushed a commit that referenced this pull request Jul 26, 2024
Can't tell you how I missed undoing a check against absolutized version
of an exe, but glad babashka CI didn't miss it!

Addendum for #165
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants