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

process.cwd() symlink behavior is undocumented #45617

Open
Trott opened this issue Nov 24, 2022 · 11 comments
Open

process.cwd() symlink behavior is undocumented #45617

Trott opened this issue Nov 24, 2022 · 11 comments

Comments

@Trott
Copy link
Member

Trott commented Nov 24, 2022

Not sure if I have to open a new issue, but there is exactly the same problem with process.cwd(). It resolves symlinks if there are any and this is not documented. I believe this also should at least be clarified in the docs.

Also, I think there should be a way to have the ability to find out both cwd and __filename/__dirname without symlinks resolved. For cwd() that can be an optional argument, for __dirname that can be some new module variables like __dirnamePreserveSymlinks.

Or maybe these things should respect --preserve-symlinks cli option. They are not doing this at least on mac os.

Originally posted by @romamik in #22602 (comment)

@Trott
Copy link
Member Author

Trott commented Nov 24, 2022

Not sure if I have to open a new issue, but there is exactly the same problem with process.cwd(). It resolves symlinks if there are any and this is not documented. I believe this also should at least be clarified in the docs.

On Unix-like operating systems, libuv uses getcwd() which will never return a symlink in the path. So this should be true for all Unix-like operating systems, unless there is a variant that violates that POSIX requirement for getcwd().

On Windows, libuv uses GetCurrentDirectoryW(), and does not (or might not but might in some situations? I'm not sure) resolve symlinks. See #34866.

So if we're going to document this one, we'll want to be careful to get it right.

Pinging teams that contain people that will know better than me: @nodejs/libuv @nodejs/platform-windows

@bnoordhuis
Copy link
Member

POSIX captures existing behavior so I'd say it's a good bet all UNIX-like platforms work that way.

I've opened libuv/libuv#3828 to discuss the UNIX vs. Windows inconsistency.

@ThePlenkov
Copy link

Somehow - this issue appeared to be a reason of a follow-up issues with devcontainers:

devcontainers/cli#932

which results in a problem with VS Code:
microsoft/vscode-remote-release#10301

and prevents to solve another problem caused by docker:
docker/for-win#14380

Unfortunately neither --preserve-symlinks nor NODE_PRESERVE_SYMLINKS=1 do not help to solve process.cwd( ).

So the only method which is supposed to give the real folder - does not work as expected.

I'd prefer if process.cwd returns the actual folder and if you need realpath you should do something like fs.realpath(process.cwd( ) )

What do you think of this?

@ThePlenkov
Copy link

also requested a flag to be added: #56288

@saghul
Copy link
Member

saghul commented Dec 17, 2024

As @Trott mentioned getcwd (what is used on Unix systems) is defined not to return symlinks. There is no flag that can change that.

You could read the PWD variable on you app code, but it's not updated in case of chdir so care must be taken...

@ThePlenkov
Copy link

but that's what I mean, can't we introduce a new flag/option forcing node not to use this getcwd but to use something else? For example pwd in Linux? I still do not understand why exec('pwd') can return what we need, but process.cwd cannot.. May be we can route this logic on Unix systems somehow

@saghul
Copy link
Member

saghul commented Dec 17, 2024

In a nutshell pwd will return the PWD encironment variable and getcwd if called with -P: https://github.com/coreutils/coreutils/blob/master/src/pwd.c

Since reading the env var is fragile I'd say this would be better addressed in the app. Is that not possible?

@ThePlenkov
Copy link

well - indeed - that's possible , but it means that in my case for example - if I want to open some folder in a devcontainer in vscode, from a folder like ~/workspace and I want it to be run with cwd /home/workspace/ and not real path /mnt/wsl/workspace . - in this case we need:

  • modify devontainer CLI to support some cwd flag explicityl
  • modify vs code remote extension to propagate this flag to a devcontainer CLI

Which is still long way to go.

Meanwhile at same time I clearly see something like:
export NODE_USE_PWD_CWD=1 and then just run vs code in my folder and it would already make installed node to resolve this folder properly, so same code from devcontainers, vscode would just work with a new CWD=PWD.

That's kind of idea why env variable can be better even if it's fragile.

@saghul
Copy link
Member

saghul commented Dec 17, 2024

I guess my question is what changed that made this a problem now, since process.cwd() has always behaved like that, from its inception.

@ThePlenkov
Copy link

Oh.. i think it's a combination of some few factors. In my case it's an internal Docker problem - that it cannot mount somehow mounted folder ( folder is mount to wsl and I try to mount it to another container ), but it does with symlinked folder ( i have no clue why).
Tools which are used to wrap that docker command into a logic are written in NodeJS ( vs-code, devcontainers ), just rely on process.cwd( ) so from their perspective the app is running in a right place, so they use the result of command like process.cwd( ) to pass as arguments to another command like docker.
So in the end it creates a certain conflict. I am very much surprised how deep I could come with this drill.

At same time I understand that using symlinked CWD can be a problem for many tools like file watchers. However flags like --resolve-symlinks or env variable NODE_PRESERVE_SYMLINKS already suppose to do this partially and the were created on purpose I guess. I think summary of reasons may be like:

  • Preserving User Intent
  • Integration with external tools like Git, Docker etc which sometimes rely on symlinked path as in my case
  • User-Friendly Logging

@bnoordhuis
Copy link
Member

I'd say it's out of the question for node to use $PWD, gated on a flag or not. Native modules can call chdir(2) and that would not be visible to node.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants