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

Possible Windows Node 6 regression with spawn and a substed drive #6500

Closed
xzyfer opened this issue May 1, 2016 · 35 comments
Closed

Possible Windows Node 6 regression with spawn and a substed drive #6500

xzyfer opened this issue May 1, 2016 · 35 comments
Labels
child_process Issues and PRs related to the child_process subsystem. windows Issues and PRs related to the Windows platform.

Comments

@xzyfer
Copy link

xzyfer commented May 1, 2016

  • Version:
    v6.0.0
  • Platform:
    Windows 32 and 64 bit
  • Subsystem:

I've noticed a minor breaking change in either child_process.spawn or path.resolve (currently unclear), on Windows with Node 6. This issue appears to crop up when a Node script is execute from a SUBST'd path.

The production steps are tricky so I have created a reproduction in a repo that runs its tests in AppVeyor.

@xzyfer
Copy link
Author

xzyfer commented May 1, 2016

This may be related to #5950.

@saper
Copy link

saper commented May 1, 2016

Wow! I'm amazed.

@saper
Copy link

saper commented May 1, 2016

@xzyfer can you rename the issue to "substed" ? (or reference "drive created by subst.exe") - only few MS-DOS die-hards like me remember, what a "substed drive" is.

@xzyfer xzyfer changed the title Possible Windows Node 6 regression with spawn and subset Possible Windows Node 6 regression with spawn and a substed drive May 1, 2016
@xzyfer
Copy link
Author

xzyfer commented May 1, 2016

updated

@mscdex mscdex added child_process Issues and PRs related to the child_process subsystem. windows Issues and PRs related to the Windows platform. labels May 1, 2016
saper added a commit to saper/node-sass that referenced this issue May 1, 2016
Node 6.x has trouble probably including
modules from the substed drivers.
Since we use use subst only to set
symbols paths in the PDB file, let's
revert to the C: drive when doing tests.

Workaround for: nodejs/node#6500
saper added a commit to saper/node-sass that referenced this issue May 1, 2016
Node 6.x has trouble including modules
from MS-DOS drives created with subst.exe.

Since we use use subst only to set
symbols paths in the PDB file, let's
revert to the C: drive when doing tests.

Workaround for: nodejs/node#6500
saper added a commit to saper/node-sass that referenced this issue May 1, 2016
Node 6.x has trouble including modules
from MS-DOS drives created with subst.exe.

Since we use use subst only to set
symbols paths in the PDB file, let's
revert to the C: drive when doing tests.

Workaround for: nodejs/node#6500
saper added a commit to saper/node-sass that referenced this issue May 1, 2016
Node 6.x has trouble including modules
from MS-DOS drives created with subst.exe.

Since we use use subst only to set
symbols paths in the PDB file, let's
revert to the C: drive when doing tests.

Workaround for: nodejs/node#6500

[ci skip]
saper added a commit to saper/node-sass that referenced this issue May 1, 2016
Node 6.x has trouble including modules
from MS-DOS drives created with subst.exe.

Since we use use subst only to set
symbols paths in the PDB file, let's
revert to the C: drive when doing tests.

Workaround for: nodejs/node#6500
xzyfer pushed a commit to sass/node-sass that referenced this issue May 2, 2016
Node 6.x has trouble including modules
from MS-DOS drives created with subst.exe.

Since we use use subst only to set
symbols paths in the PDB file, let's
revert to the C: drive when doing tests.

Workaround for: nodejs/node#6500
@saper
Copy link

saper commented May 2, 2016

I have built node 7.0.0 (fa542eb) and the issue is still there. Reverting de1dc0a fixes the issue - npm test done one a substed drive passes.

@xzyfer
Copy link
Author

xzyfer commented May 2, 2016

Nice find @saper

@jasnell
Copy link
Member

jasnell commented May 2, 2016

Yep, de1dc0a fixed another bug but led to some other regressions. There is work underway to find a workaround that would address both sets of concerns but it's non-trivial. This is queued up already for @nodejs/ctc discussion this week to see if we need to revert or find another path forward.

@kzc
Copy link

kzc commented May 2, 2016

Is SUBST the Windows equivalent of a symlink?

mkdir c:\projects
cd c:\projects
git clone https://github.com/xzyfer/node-6-native-ext-bug.git
cd node-6-native-ext-bug
subst s: c:\projects
npm install
npm test

If you cd to s:\node-6-native-ext-bug does npm test run successfully?

@saper
Copy link

saper commented May 2, 2016

Subst is the ancient feature, coming from MSDOS times. It is more like Unix nullfs - mounting some subdirectory under the new name. But Unix does not have drive letters.

and yes, it failes when you are "on" a substed drive. Compiling from C:\projects works.

@kzc
Copy link

kzc commented May 2, 2016

Thanks @saper. In the DOS days I'm sure I used SUBST but knowledge of it was pushed out of my brain.

So a SUBST'd drive is similar to a symlink. However unlike a symlink, it changes the original source directory into the logical link and treats the new drive as the realpath? How odd. This seems backwards.

If this same example were run with node 5.x or earlier, does npm test still run within the subst'd directory s:\node-6-native-ext-bug? If my theory is correct it won't.

@saper
Copy link

saper commented May 2, 2016

Yes, all the tests ran correctly.

realpath is nothing magical, it tries to do its job to some extent. Node uses libuv, and its implementation of realpath for Windows uses GetFinalPathNameByHandle Windows API, which is not enough in this case. One had to use QueryDosDevice API. But there is also JOIN.EXE to makes things even harder. (Or ASSIGN.EXE, which seems to be gone from the most recent Windows releases).

@kzc
Copy link

kzc commented May 2, 2016

@saper Okay this should be fixable. To your point, libuv fs__realpath_handle should implement the algorithm in http://pdh11.blogspot.ca/2009/05/pathcanonicalize-versus-what-it-says-on.html for realpathing of SUBST drives which should fix the situation.

Can you please confirm that if you use windows symlinks instead of SUBST - does npm test work in both the original and symlinked directory with node 6.0.0? Not knowing anything about Windows symlinks, google tells me Admin privileges may be required.

@saper
Copy link

saper commented May 2, 2016

Well, yes. But in general I avoid using realpath as much as possible. node-sass has been using it to get the one true path of the node executable and we gave up sass/node-sass#1323.

@kzc
Copy link

kzc commented May 2, 2016

Alright then, this appears to be a Windows libuv realpath issue, not a module resolution problem.

@saper
Copy link

saper commented May 2, 2016

No, that's not true. The fix in the module is incorrect. It aims at improving __dirname, it breaks things instead.

@kzc
Copy link

kzc commented May 2, 2016

After the SUBST command is run, what is fs.realpathSync("c:/projects/node-6-native-ext-bug")? (assuming I got the Windows path format right)

Edit: In the new node 6.0.0 module resolution scheme the main script is still realpathed to get the right directory, but the other modules are not. This is why I think it's a libuv realpath issue if the expression above returns the wrong path.

@saper
Copy link

saper commented May 2, 2016

C:\Projects\node-6-native-ext-bug>v:\sw\node\Release\node -p fs.realpathSync('s:\\node-6-native-ext-bug')
C:\Projects\node-6-native-ext-bug

C:\Projects\node-6-native-ext-bug>v:\sw\node\Release\node -p fs.realpathSync('c:\\projects\\node-6-native-ext-bug')
C:\Projects\node-6-native-ext-bug

C:\Projects\node-6-native-ext-bug>subst
S:\: => C:\projects

So, realpath seems to work fine here.

@kzc
Copy link

kzc commented May 2, 2016

Okay, there goes that theory.

If the same test is run with path.resolve instead of fs.realpathSync do you get the same result?

@saper
Copy link

saper commented May 2, 2016

C:\Projects\node-6-native-ext-bug>v:\sw\nodebrk -p path.resolve('s:\\node-6-native-ext-bug')
s:\node-6-native-ext-bug

C:\Projects\node-6-native-ext-bug>v:\sw\nodebrk -p path.resolve('c:\\projects\\node-6-native-ext-bug')
c:\projects\node-6-native-ext-bug

C:\Projects\node-6-native-ext-bug>subst
S:\: => C:\projects

@kzc
Copy link

kzc commented May 2, 2016

I see. libuv handles SUBST correctly. Thanks.

@kzc
Copy link

kzc commented May 2, 2016

Would it possible to get the value of require.resolve('buffertools') with node 6.0.0 when the command is run from C:\Projects\node-6-native-ext-bug and then from s:\node-6-native-ext-bug?

@saper
Copy link

saper commented May 2, 2016

C:\Projects\node-6-native-ext-bug>v:\sw\nodebrk.exe -p require.resolve('buffertools')
C:\Projects\node-6-native-ext-bug\node_modules\buffertools\buffertools.js

C:\Projects\node-6-native-ext-bug>s:

S:\>cd node-6-native-ext-bug

S:\node-6-native-ext-bug>v:\sw\nodebrk.exe -p require.resolve('buffertools')
S:\node-6-native-ext-bug\node_modules\buffertools\buffertools.js

@saper
Copy link

saper commented May 2, 2016

I think this problem is pretty easy to see from the npm test output:

Spawning: node S:\node-6-native-ext-bug\loader.js
Executing: C:\Projects\node-6-native-ext-bug\loader.js
Requiring: C:\Projects\node-6-native-ext-bug\node_modules\buffertools\build\Release\buffertools.node

The above lines run in a fresh copy of node (spawned) and have isMain true.
de1dc0a#diff-d1234a869b3d648ebfcdce5a76747d71R117 when isMain is true, we are using realpath to convert the path to the One True Path.

Then a module is included, and isMain ceases to be true now:

Requiring: S:\node-6-native-ext-bug\subloader.js
Executing: S:\node-6-native-ext-bug\subloader.js
Requiring: S:\node-6-native-ext-bug\node_modules\buffertools\build\Release\buffertools.node

Now we take another code path de1dc0a#diff-d1234a869b3d648ebfcdce5a76747d71R119 and we are not converting the path to the One True Path.

Therefore another attempt to load the binary module is undertook, which brings a whole thing down.

@kzc
Copy link

kzc commented May 2, 2016

/cc @dlongley @lamara

@MylesBorins
Copy link
Contributor

MylesBorins commented May 2, 2016

/cc @alexanderGugel

@jasnell
Copy link
Member

jasnell commented May 2, 2016

See: #6537

@dlongley
Copy link

dlongley commented May 3, 2016

@saper,

Could you just add an additional require to get around the isMain issue?

@dlongley
Copy link

dlongley commented May 3, 2016

I'd be +1 to removing the isMain flag and never using realpath at all, by default. Not sure what the consequences of that would be, however.

@saper
Copy link

saper commented May 3, 2016

@dlongley node needs to use realpath not to try to load the same binary module twice. It's clunky, but that's how it currently works...

@dlongley
Copy link

dlongley commented May 3, 2016

@saper,

node needs to use realpath not to try to load the same binary module twice. It's clunky, but that's how it currently works...

Then we should only do realpath on binary modules.

@kzc
Copy link

kzc commented May 3, 2016

@saper Earlier in this thread I asked if the same test case worked with node 6.0.0 with a symlink instead of SUBST. Just wanted to confirm that this is true or if I misinterpreted you. Just trying to determine the scope of the issue and whether symlinks are a workaround.

@saper
Copy link

saper commented May 3, 2016

I have not tried to reproduce it with symlinks before, I have only used SUBST.EXE.

But yesterday I wrote a test case for node to check for this issue and I have made the test case use MKLINK.EXE (the symbolic linking on Windows) if it gets administrative privileges. The symptoms are the same (it does not matter if one uses SUBST or MKLINK).

@evanlucas
Copy link
Contributor

@xzyfer can you please try v6.2.0 and see if the problem still exists? Thanks!

xzyfer added a commit to sass/node-sass that referenced this issue Jun 7, 2016
This reverts commit 15fe42e to
assert nodejs/node#6500 is resolved in Node v6.2.0.
xzyfer added a commit to sass/node-sass that referenced this issue Jun 7, 2016
This reverts commit 15fe42e to
assert nodejs/node#6500 is resolved in Node v6.2.0.
xzyfer added a commit to sass/node-sass that referenced this issue Jun 7, 2016
This reverts commit 15fe42e to
assert nodejs/node#6500 is resolved in Node v6.2.0.
@xzyfer
Copy link
Author

xzyfer commented Jun 7, 2016

@evanlucas I can confirm this is fixed in Node v6.2.0 in both my reduced reproduction and in the larger node-sass ci.

@evanlucas
Copy link
Contributor

Glad to hear. Closing as this has been fixed. Thanks!!

xzyfer added a commit to xzyfer/node-sass that referenced this issue Dec 10, 2016
This was originally removed in sass#1514 to work around nodejs/node#6500
which has since been resolved. This isn't playing nice with our npm
cache in CI because we're changing the current path after running
npm install.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
child_process Issues and PRs related to the child_process subsystem. windows Issues and PRs related to the Windows platform.
Projects
None yet
Development

No branches or pull requests

8 participants