-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
test: implement setproctitle for windows #14042
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,36 +7,65 @@ if (common.isSunOS) | |
| common.skip(`Unsupported platform [${process.platform}]`); | ||
|
|
||
| const assert = require('assert'); | ||
| const exec = require('child_process').exec; | ||
| const { exec, spawn } = require('child_process'); | ||
| const path = require('path'); | ||
|
|
||
| // The title shouldn't be too long; libuv's uv_set_process_title() out of | ||
| // security considerations no longer overwrites envp, only argv, so the | ||
| // maximum title length is possibly quite short. | ||
| let title = String(process.pid); | ||
| const title = String(Date.now()).substr(-4, 4); | ||
|
|
||
| assert.notStrictEqual(process.title, title); | ||
| process.title = title; | ||
| assert.strictEqual(process.title, title); | ||
| if (process.argv[2] === 'child') { | ||
| const childTitle = process.argv[3]; | ||
| assert.notStrictEqual(process.title, childTitle); | ||
| process.title = childTitle; | ||
| assert.strictEqual(process.title, childTitle); | ||
| // Just wait a little bit before exiting | ||
| setTimeout(() => {}, common.platformTimeout(300)); | ||
| return; | ||
| } | ||
|
|
||
| // Test setting the title but do not try to run `ps` on Windows. | ||
| if (common.isWindows) | ||
| common.skip('Windows does not have "ps" utility'); | ||
| // This should run only in the parent | ||
| assert.strictEqual(process.argv.length, 2); | ||
| let child; | ||
| const cmd = (() => { | ||
| if (common.isWindows) { | ||
| // For windows we need to spawn a new `window` so it will get the title. | ||
| // For that we need a `shell`, and to use `start` | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could do with a short comment here stating that changing the title on Windows changes the title of the Window, which may not be the |
||
| child = spawn( | ||
| 'start /MIN /WAIT', | ||
| [process.execPath, __filename, 'child', title], | ||
| { shell: true, stdio: 'ignore' }, | ||
| ); | ||
| const PSL = 'Powershell -NoProfile -ExecutionPolicy Unrestricted -Command'; | ||
| const winTitle = '$_.mainWindowTitle'; | ||
| return `${PSL} "ps | ? {${winTitle} -eq '${title}'} | % {${winTitle}}"`; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is subject to race condition, where the PowerShell script may run before the spawned child process changes the title? Maybe we can use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll research that, also I think there is a guarantee that something (not sure what) has to finish before
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P.S. I have seen inconsistant results but I attributed them to the child exiting too soon 🤔
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, with IPC we could get the child to wait around instead of arbitrary timeout.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't use IPC because the script is run not in the child but in a grandchild created with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, is there any solution to this? Because without this solved it seems like there can not be any progress. |
||
| } else { | ||
| // for non Windows we change our own title | ||
| assert.notStrictEqual(process.title, title); | ||
| process.title = title; | ||
| assert.strictEqual(process.title, title); | ||
|
|
||
| // To pass this test on alpine, since Busybox `ps` does not | ||
| // support `-p` switch, use `ps -o` and `grep` instead. | ||
| const cmd = common.isLinux ? | ||
| `ps -o pid,args | grep '${process.pid} ${title}' | grep -v grep` : | ||
| `ps -p ${process.pid} -o args=`; | ||
| // To pass this test on alpine, since Busybox `ps` does not | ||
| // support `-p` switch, use `ps -o` and `grep` instead. | ||
| return common.isLinux ? | ||
| `ps -o pid,args | grep '${process.pid} ${title}' | grep -v grep` : | ||
| `ps -p ${child.pid} -o args=`; | ||
| } | ||
| })(); | ||
|
|
||
| exec(cmd, common.mustCall((error, stdout, stderr) => { | ||
| // We don't need the child anymore... | ||
| if (child) { | ||
| child.kill(); | ||
| child.unref(); | ||
| } | ||
| assert.ifError(error); | ||
| assert.strictEqual(stderr, ''); | ||
| const ret = stdout.trim(); | ||
|
|
||
| // freebsd always add ' (procname)' to the process title | ||
| if (common.isFreeBSD) | ||
| title += ` (${path.basename(process.execPath)})`; | ||
|
|
||
| // omitting trailing whitespace and \n | ||
| assert.strictEqual(stdout.replace(/\s+$/, '').endsWith(title), true); | ||
| // freeBSD adds ' (procname)' to the process title | ||
| const bsdSuffix = ` (${path.basename(process.execPath)})`; | ||
| const expected = title + (common.isFreeBSD ? bsdSuffix : ''); | ||
| assert.strictEqual(ret.endsWith(expected), true); | ||
| assert.strictEqual(ret.endsWith(expected), true); | ||
| })); | ||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this change? (to clarify: I’m sure there’s a reason, I just don’t see it?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was checking what is actually the limit, and it turns out to be 4 chars, and it fails on my machine (when pid > 10000), so I picked a fairly random seed, and truncated to 4.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use a constant value then? I know this wasn’t the case before, but it’s not really a good idea to use random values in tests, where reproducibility matters (alternative: print the title to stderr, that should work as well)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohhh. that's a good idea!
...
But it only give us node's "internal" view, while
psgives us how the external system sees the title...
The issue with a constant value is that zombies will give us a false positive. We need a secret that only know to the testing process
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right. Yeah, in that case, print it out to stderr.