-
Notifications
You must be signed in to change notification settings - Fork 28.9k
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
Correctly inherit/don't inherit the shell environment #55194
Conversation
This was a deliberate decision AFAIK to only evaluate the environment on the main process once and then have all windows inherit it. I'm curious to hear @joaomoreno's perspective on this when he gets a chance. |
If I'm understanding things correctly, the behavior before this PR is as such:
The column indicates the type of the first launch, while the row indicates the second. The cell indicates from where the second launch gets it's environment from. This behavior doesn't look right to me. Why should the first launch matter for the decision of whether to use the login shell env hack? Only whether the current launch is from CLI or desktop should matter. (I guess this code is for working around desktop environments that don't run the users login shell during their startup, many actually do run it, so you do get a proper environment even when launched from desktop in those.This means this code might end up resulting in an environment where you ran the users profile script twice. Once by the desktop environment on login and once by VS Code. Potentially leading to doubled up directories in The behavior after this PR should be:
P.S. It's quite possible that the inheritance from the main process leaks unwanted environment vars into the window. For example, if the first launch is from a virtualenv, than |
Great analysis. There's a large discussion over at #15452 about this. We have not decided whether we'd want to support this, because it will bring other issues.
Can you explain this better?
Most actually do, but they end up skipping essential files which developers depend on, namely
Yup, this is a purposeful choice on our side. We prefer this than having everyone complain that they don't have Node in the PATH (nvm users).
The second row of the table shows that this PR still doesn't fix this. It seems that |
Again... Now with markdown rendered...
Don't you already try to, partially, support this? Isn't that what the login shell hack does? I think it's just a matter of getting the behavior right...
Who will complete first: The assignment of I don't think there is any guarantee that one will complete before the other (Barring any: We don't sleep anywhere before using
If they skip the There is the idiosyncrasy of Bash not sourcing In Zsh, you likely end up without You are supposed to put
Having an empty env is obviously surprising and bad. But running the login script twice can also lead to issues. My understanding is that the profile scripts can do non-idempotent things such as starting an There are often You can see what Atom does https://github.com/atom/atom/blob/5b485dcb4b48386d9480ab45dc389cbcaad3d454/src/update-process-env.js. But I'm not sure even it handles all cases correctly. It probably doesn't
The whole point is not to clobber the environment if the user runs VS Code from shell using the Before:
After:
|
Ouch, |
3959296
to
ea8c110
Compare
Sorry for that @segevfiner |
`VSCODE_CLI` was checked from the main process, which had it set depending on if the *first* launch of VS Code was launched from cli or not, instead of whether the *current* launch has it set. So I changed the check to checking the userEnv passed to the new browser window. Note that the assignment of `lazyEnv` and `userEnv` into `process.env` was racing before! Which is a bug in and of itself. After this fix, the `shellEnv`/`lazyEnv` overrides the passed in `userEnv`, but that can be changed later if needed. We are also always launching the shell now since `configuration.userEnv` is not available yet when `lazyEnv` is initialized. It will require a hack or some refactoring to fix, so I left that like this for now. Might want to open an issue for future reference. Fixes microsoft#55144
ea8c110
to
910a40f
Compare
What would be needed to achieve this behaviour? |
@ysndr Changing the logic so as to also remove env vars that don't exist in the environment from the cli or retrieved from shell except those required by VS Code (e.g. I planned on also fixing that on a separate PR, but sadly this PR has been hanging here for a long time... |
@segevfiner I did look into this once more recently... but didn't get the courage to jump into it fully. I'll try to get to it asap. |
😢 |
I know... apologies @segevfiner. I did get to it eventually. And again later. But every time I get back to it, I simply can't pull the trigger. I feel this is a big change which will have a long tail of issues of users complaining that something is changed/broken... And right now there's only <10 users talking about this and even tolerating the current behavior. I am definitely not comfortable moving this forward. I'd like to bring in @bpasero @Tyriar and @deepak1556, do you have any opinions on this? |
I don't feel comfortable to make statement because I am no user of the shell environment whatsoever in any of my code. The main users are probably:
So I would drive this change with their input and sign off. Btw with the advent of sandbox coming to the renderer we should be careful of not making the solution too node specific. I did a quick test and it seems you can still access |
Making vscode act like most other apps would be good, I have to spell out when people are having issues with the terminal to make sure that they close all the windows and try opening again, this is because it's unexpected. Just to make sure I understand things this PR does:
If that's how it works it seems good to me and shouldn't affect the terminal negatively. I'd expect tasks to be fine too since it's built on the terminal. |
@Tyriar Yeah should be like that. But does have one caveat in that env vars that are unset in the shell or the main process environment ( |
Reviewing my PR again. I noticed that Not currently sure what's the best way to fix this. Maybe a new promise for it to await instead? That is, a promise that is resolved once I'm trying to implement that change anyhow to be sure. |
Changed the code to preserve the previous behavior of Now the only remaining caveat is what I mentioned about it possibly keeping variables from the parent process that are unset in both the CLI and shell environment. Fixing that will probably mean fully cloberring EDIT: So looks like Just in case it wasn't clear. I believe this PR is ready. This last issue can be tackled separately. I think I can also change the code not to call |
@segevfiner can you resolve the merge conflicts |
This diverged so much within the year that it is pretty much doing this from scratch at this point... |
Then I suggest to close this PR and maybe you can put the suggested solution as a comment into the issue? |
I will try to redo it first on this branch first. But there might be caveats due to the electron browser<->node separation. |
I tried to redo this change. But note that I did so on Windows while this fix is really for Linux and Mac, meaning this still needs to be tested that it even still works. I'm also not sure what I did in the new |
@segevfiner thanks. you seem to indicate there is a race condition even in todays code, can you clarify? Unfortunately the assignment to |
The previous code used to assign
And this introduces a problem, for us to know if we should assign it, we need the Just reiterating so we are on the same page, the problem that this tries to fix is that VS Code is trying to check the wrong environment for |
@segevfiner thanks for finding that, I can confirm it looks suspicious. I have opened #108607 to look into it. This will also require that
Understood. One impact your change has is that we will now always resolve the shell environment on startup, even if you start from the command line. This may have a bad impact on startup perf because we need to spawn another process. A more elegant solution imho would be to really only trigger this dance for the first window that needs it. But I cannot really see a good solution for this at the moment given we resolve the shell environment once and then store the promise. |
This comment has been minimized.
This comment has been minimized.
If the preload script will have access to the configuration and we move the |
@segevfiner sorry, how can we prevent spawning a shell? The idea of this was to get the shell's environment variables when you start VSCode from e.g. the dock. So the basic functionality needs to stay like that, or am I missing something? |
Btw I just checked the code again and do not see a race condition, because the code |
I'm talking about maintaining the previous behavior of only spawning the shell when we actually need the shell environment, not about not spawning it entirely. I had to run make it spawn the shell also when we don't need it due to the configuration not being available yet when we need to decide to run it or not due to the way the current code is structured.
But it looks like the order is now that the shell env is applied after the user env, do we really sure we want the shell env to clobber over the user env rather than the other way around? Considering that user env is also the environment captured when the user runs |
@segevfiner keep in mind that we WANT to resolve the shell environment as early as possible even before opening a window because we do NOT WANT to slow down the opening of the window only to wait for the shell environment to be resolved. So we cannot move this to a later place, it has to start right on startup. And with your change we will do it ALWAYS, even when you run from the command line (as opposed to today where we do NOT spawn shell when you run from command line). I could not understand the last paragraph you wrote, sorry. I hope this clarifies things.
I cannot speak to the intent of this as I am not the original author of this flow, I just try to preserve what we had before and explain that there is no race condition. |
Of course. If the configuration is available early enough in the window startup or at least what we need to determine this condition, then we can start it right away in parallel as is today, just with the condition inside the
Might need to rope in whoever is familiar with this, cause it doesn't feel right, should the shell env really be allowed to override env vars set by VS Code itself? |
I am closing this in favour of #108804 which I plan to look at during this month. I also want to support and/or understand #15452 and #108571 Work happens in https://github.com/microsoft/vscode/tree/dev/execution-service |
@segevfiner btw thanks for putting us on the right track for how to resolve these issues and sorry for the long time this took. You are right for example that there is a race condition where the user environment gets overwritten by the shell-probe-environment and we plan to fix all these issues. After discussion with @joaomoreno I documented our proposed solution in #108804 (comment) |
VSCODE_CLI
was checked from the main process, which had it set depending on if the first launch of VS Code was launched from cli or not, instead of whether the current launch has it set.So I changed the check to checking the
userEnv
passed to the new browser window.Note that the assignment of
lazyEnv
anduserEnv
intoprocess.env
was racing before! Which is a bug in and of itself. After this fix, theshellEnv
/lazyEnv
overrides the passed inuserEnv
, but that can be changed later if needed.We are also always launching the shell now since
configuration.userEnv
is not available yet whenlazyEnv
is initialized. It will require a hack or some refactoring to fix, so I left that like this for now. Might want to open an issue for future reference.Fixes #55144
Part of #15452