-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
AIX: parallel/test-stdio-closed #8375
Comments
@nodejs/testing @Fishrock123 |
If it helps anyone troubleshoot or if it gives anyone an idea as to what's going on, the
/cc gireeshpunathil who might have more information to add since their last comment. |
Also, if it helps anyone, here's the modified version of the test I used to capture that info: 'use strict';
const common = require('../common');
const assert = require('assert');
const spawn = require('child_process').spawn;
if (common.isWindows) {
common.skip('platform not supported.');
return;
}
if (process.argv[2] === 'child') {
try {
process.stdout.write('stdout', function() {
try {
process.stderr.write('stderr', function() {
process.exit(42);
});
} catch (e) {
process.exit(200);
}
});
} catch (e) {
process.send(e.code);
process.send(e.message);
process.exit(20);
}
return;
}
// Run the script in a shell but close stdout and stderr.
const cmd = `"${process.execPath}" "${__filename}" child 1>&- 2>&-`;
const proc = spawn(
'/bin/sh', ['-c', cmd], { stdio: ['ipc', 'inherit', 'inherit'] }
);
proc.on('message', (msg) => {
console.log(msg);
});
proc.on('exit', common.mustCall(function(exitCode) {
assert.strictEqual(exitCode, 42);
})); Here's the results. I believe the
|
Thanks @Trott - this info will be really useful, I will investigate. |
ok, putting things into perspective: Three processes: a node parent spawns a non-node child (sh) which closes its streams (1 and 2) and then spawns a node child. The grandchild attempts to write to its stream, and then returns an error code. In Linux, the grandchild node apparently succeeded in writing into stdout, while AIX failed with EBADF (fd closed | invalid) |
So the question is, who closed the grandchild node's stream in AIX. resorting to truss (AIX) and strace (Linux), I see that the parent shell does not perform fork and exec, instead only exec - means the closed streams of sh is inherited to the node grandchild: Linux:
AIX:
This is also visible if I add a timeout in the grandchild and examine the processes: Linux:
AIX:
As we can see, there is no /bin/sh in the list. That process itself exec'ed into node. So, for the grandchild node, fd 1 is inherently closed. |
I wrote a C grandchild and used the same test case to invoke it to see how it behaves:
Linux:
AIX:
Here Linux and AIX behaved in the same manner, and the reason is well understood - the grandchild's fd is closed at inception. So, Linux node seem to have special method to handle closed standard streams: either re-incarnate them through /dev/null device, or suppress the error code from propagation. AIX may be missing this. At this point, I want to question the Linux behavior: Functionally, a node process spawned with standard streams suppressed, should behave in a console-less manner, and attempts to write to them should err. Any thoughts? |
@gireeshpunathil This test is designed specifically to test that code. And it seems that either that code is not running on AIX (maybe the Any ideas? |
Thanks @Trott ! I was looking for such a location. I will now figure out what is happening out there in AIX. |
@gireeshpunathil What is the result without $ node -e "process.stdout.write('aaa')" 1>&- @Trott (This is just guess) The code with fstat() is surrounded by EDIT: I also found |
|
I tested that at first, but it succeeded all the time:
|
I guess I found the infliction point:
Linux:
AIX:
Need to map it back into the problem context, and figure out how this led to the issue. Also need to dig into fstat manuals to understand the disparity. |
seems fstat() is there to check stdio fds open. |
ok, sounds reasonable explanation, thanks @veshboo! |
I recommend to have |
Sounds like that, but why? |
will continue debugging tomorrow. |
Regarding this working on AIX even though the test here is failing: ./node -e "process.stdout.write('aaa')" 1>&- What about this instead?: ./node -e "process.stdout.write('aaa', () => { console.error('write was successful-ish'); })" 1>&- |
I wade into C++ observations with trepidation as I feel like a complete imposter on this stuff, but HERE WE GO:
/cc @bnoordhuis who introduced both the |
Also:
EDIT: Upon further reflection, skipping might not be OK if it means the potential information leak is there. On the other hand, perhaps the information leak is there too on Windows so... |
So, yes, that may be a bug in AIX then. I could also imagine that something in the background opens another FD before the |
@gireeshpunathil What kind of file descriptor does |
@bnoordhuis I'm seeing AIX report a regular file ( |
I have machine access issues right now, hoping to resume my work soon. |
Perl does it for stdin but not stdout:
|
@bnoordhuis Do you have an opinion as to which of these is the right way to approach solving this issue?
|
I think it's a good feature to have; I wrote the code for a reason. :-) The reason to make sure fds 0-2 refer to something is that it's a potential data leak otherwise. Imagine an attacker manages to open a socket with fd 1 - they will receive everything that the application prints through |
@bnoordhuis Would I be correct to conclude that if it turns out it can't be reliably implemented on AIX, then skipping the test on AIX would be your preference and leave the feature alone on other POSIX instances? |
Correct. |
I suppose another option is to alter the test to confirm that if a stdio stream is closed on startup, that it can't be re-opened. It does mean accepting a behavior difference: Linux (for example) will silently discard writes to the "closed" stream (which will really be re-opened but pointed at |
|
Switched the
Still fails on AIX: https://ci.nodejs.org/job/node-stress-single-test/918/nodes=aix61-ppc64/console Given the results from a couple days ago, I don't think any tweak to the |
There is |
I'm afraid that appears to have no effect on the test outcome. https://ci.nodejs.org/job/node-stress-single-test/920/nodes=aix61-ppc64/console
|
@Trott while I still want us to better figure out if there is a bug on AIX, I think that:
Given that I'm ok with your suggestion of allowing "AIX throwing EBADF" as a pass for the test on AIX only or disabling the test for AIX with my preference being the former. If we do that we'd still investigate to see if we can come to a more complete understanding/fix. @gireeshpunathil @bnoordhuis thoughts ? |
AIX handles closed stdio differently (but still compliant with spec as far as I can tell) than other POSIX variants we test. Test results are different than Linux and others because AIX takes measures to not re-use the file descriptors for stdio if one of the stdio streams is closed. Fixes: nodejs#8375
AIX handles closed stdio differently (but still compliant with spec as far as I can tell) than other POSIX variants we test. Test results are different than Linux and others because AIX takes measures to not re-use the file descriptors for stdio if one of the stdio streams is closed. Fixes: #8375 PR-URL: #8755 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]> Reviewed-By: Ilkka Myller <[email protected]>
AIX handles closed stdio differently (but still compliant with spec as far as I can tell) than other POSIX variants we test. Test results are different than Linux and others because AIX takes measures to not re-use the file descriptors for stdio if one of the stdio streams is closed. Fixes: #8375 PR-URL: #8755 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]> Reviewed-By: Ilkka Myller <[email protected]>
AIX handles closed stdio differently (but still compliant with spec as far as I can tell) than other POSIX variants we test. Test results are different than Linux and others because AIX takes measures to not re-use the file descriptors for stdio if one of the stdio streams is closed. Fixes: nodejs#8375 PR-URL: nodejs#8755 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]> Reviewed-By: Ilkka Myller <[email protected]>
AIX handles closed stdio differently (but still compliant with spec as far as I can tell) than other POSIX variants we test. Test results are different than Linux and others because AIX takes measures to not re-use the file descriptors for stdio if one of the stdio streams is closed. Fixes: #8375 PR-URL: #8755 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]> Reviewed-By: Ilkka Myller <[email protected]> Conflicts: test/parallel/parallel.status
AIX handles closed stdio differently (but still compliant with spec as far as I can tell) than other POSIX variants we test. Test results are different than Linux and others because AIX takes measures to not re-use the file descriptors for stdio if one of the stdio streams is closed. Fixes: #8375 PR-URL: #8755 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]> Reviewed-By: Ilkka Myller <[email protected]>
AIX handles closed stdio differently (but still compliant with spec as far as I can tell) than other POSIX variants we test. Test results are different than Linux and others because AIX takes measures to not re-use the file descriptors for stdio if one of the stdio streams is closed. Fixes: #8375 PR-URL: #8755 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Gibson Fahnestock <[email protected]> Reviewed-By: Ilkka Myller <[email protected]>
Version: master
Platform: AIX
Subsystem: io
parallel/test-stdio-closed fails on AIX, pulling this out of #7973 to avoid confusion since issues are not related.
The text was updated successfully, but these errors were encountered: