Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cc6ec2f

Browse filesBrowse files
bnoordhuisjasnell
authored andcommitted
inspector: bind to random port with --inspect=0
Allow binding to a randomly assigned port number with `--inspect=0` or `--inspect-brk=0`. PR-URL: #5025 Refs: #4419 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
1 parent a2d4954 commit cc6ec2f
Copy full SHA for cc6ec2f

File tree

Expand file treeCollapse file tree

6 files changed

+99
-4
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

6 files changed

+99
-4
lines changed
Open diff view settings
Collapse file

‎src/inspector_io.cc‎

Copy file name to clipboardExpand all lines: src/inspector_io.cc
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ InspectorIo::InspectorIo(Environment* env, v8::Platform* platform,
175175
io_thread_req_(), platform_(platform),
176176
dispatching_messages_(false), session_id_(0),
177177
script_name_(path),
178-
wait_for_connect_(wait_for_connect) {
178+
wait_for_connect_(wait_for_connect), port_(-1) {
179179
main_thread_req_ = new AsyncAndAgent({uv_async_t(), env->inspector_agent()});
180180
CHECK_EQ(0, uv_async_init(env->event_loop(), &main_thread_req_->first,
181181
InspectorIo::MainThreadAsyncCb));
@@ -298,6 +298,7 @@ void InspectorIo::WorkerRunIO() {
298298
uv_sem_post(&start_sem_);
299299
return;
300300
}
301+
port_ = server.port(); // Safe, main thread is waiting on semaphore.
301302
if (!wait_for_connect_) {
302303
uv_sem_post(&start_sem_);
303304
}
Collapse file

‎src/inspector_io.h‎

Copy file name to clipboardExpand all lines: src/inspector_io.h
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class InspectorIo {
6868
uv_close(reinterpret_cast<uv_handle_t*>(&io_thread_req_), nullptr);
6969
}
7070

71+
int port() const { return port_; }
72+
7173
private:
7274
template <typename Action>
7375
using MessageQueue =
@@ -129,6 +131,7 @@ class InspectorIo {
129131
std::string script_path_;
130132
const std::string id_;
131133
const bool wait_for_connect_;
134+
int port_;
132135

133136
friend class DispatchMessagesTask;
134137
friend class IoSessionDelegate;
Collapse file

‎src/node.cc‎

Copy file name to clipboardExpand all lines: src/node.cc
+13-1Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
#include "node_i18n.h"
4141
#endif
4242

43+
#if HAVE_INSPECTOR
44+
#include "inspector_io.h"
45+
#endif
46+
4347
#if defined HAVE_DTRACE || defined HAVE_ETW
4448
#include "node_dtrace.h"
4549
#endif
@@ -3048,7 +3052,15 @@ static Local<Object> GetFeatures(Environment* env) {
30483052

30493053
static void DebugPortGetter(Local<Name> property,
30503054
const PropertyCallbackInfo<Value>& info) {
3051-
info.GetReturnValue().Set(debug_options.port());
3055+
int port = debug_options.port();
3056+
#if HAVE_INSPECTOR
3057+
if (port == 0) {
3058+
Environment* env = Environment::GetCurrent(info);
3059+
if (env->inspector_agent()->IsStarted())
3060+
port = env->inspector_agent()->io()->port();
3061+
}
3062+
#endif // HAVE_INSPECTOR
3063+
info.GetReturnValue().Set(port);
30523064
}
30533065

30543066

Collapse file

‎src/node_debug_options.cc‎

Copy file name to clipboardExpand all lines: src/node_debug_options.cc
+3-2Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ int parse_and_validate_port(const std::string& port) {
2121
char* endptr;
2222
errno = 0;
2323
const long result = strtol(port.c_str(), &endptr, 10); // NOLINT(runtime/int)
24-
if (errno != 0 || *endptr != '\0'|| result < 1024 || result > 65535) {
25-
fprintf(stderr, "Debug port must be in range 1024 to 65535.\n");
24+
if (errno != 0 || *endptr != '\0'||
25+
(result != 0 && result < 1024) || result > 65535) {
26+
fprintf(stderr, "Debug port must be 0 or in range 1024 to 65535.\n");
2627
exit(12);
2728
}
2829
return static_cast<int>(result);
Collapse file
+32Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Flags: --inspect=0
2+
'use strict';
3+
4+
const common = require('../common');
5+
const assert = require('assert');
6+
const cluster = require('cluster');
7+
8+
if (cluster.isMaster) {
9+
const ports = [];
10+
for (const worker of [cluster.fork(),
11+
cluster.fork(),
12+
cluster.fork()]) {
13+
worker.on('message', common.mustCall((message) => {
14+
ports.push(message.debugPort);
15+
worker.kill();
16+
}));
17+
worker.send('debugPort');
18+
}
19+
process.on('exit', () => {
20+
ports.sort();
21+
assert.strictEqual(ports.length, 3);
22+
assert(ports.every((port) => port > 0));
23+
assert(ports.every((port) => port < 65536));
24+
assert.strictEqual(ports[0] + 1, ports[1]); // Ports should be consecutive.
25+
assert.strictEqual(ports[1] + 1, ports[2]);
26+
});
27+
} else {
28+
process.on('message', (message) => {
29+
if (message === 'debugPort')
30+
process.send({ debugPort: process.debugPort });
31+
});
32+
}
Collapse file
+46Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
'use strict';
2+
3+
const { mustCall } = require('../common');
4+
const assert = require('assert');
5+
const { URL } = require('url');
6+
const { spawn } = require('child_process');
7+
8+
function test(arg) {
9+
const args = [arg, '-p', 'process.debugPort'];
10+
const proc = spawn(process.execPath, args);
11+
proc.stdout.setEncoding('utf8');
12+
proc.stderr.setEncoding('utf8');
13+
let stdout = '';
14+
let stderr = '';
15+
proc.stdout.on('data', (data) => stdout += data);
16+
proc.stderr.on('data', (data) => stderr += data);
17+
proc.stdout.on('close', assert.ifError);
18+
proc.stderr.on('close', assert.ifError);
19+
let port = '';
20+
proc.stderr.on('data', () => {
21+
if (!stderr.includes('\n')) return;
22+
assert(/Debugger listening on (.+)/.test(stderr));
23+
port = new URL(RegExp.$1).port;
24+
assert(+port > 0);
25+
});
26+
if (/inspect-brk/.test(arg)) {
27+
proc.stderr.on('data', () => {
28+
if (stderr.includes('\n') && !proc.killed) proc.kill();
29+
});
30+
} else {
31+
let onclose = () => {
32+
onclose = () => assert.strictEqual(port, stdout.trim());
33+
};
34+
proc.stdout.on('close', mustCall(() => onclose()));
35+
proc.stderr.on('close', mustCall(() => onclose()));
36+
proc.on('exit', mustCall((exitCode) => assert.strictEqual(exitCode, 0)));
37+
}
38+
}
39+
40+
test('--inspect=0');
41+
test('--inspect=127.0.0.1:0');
42+
test('--inspect=localhost:0');
43+
44+
test('--inspect-brk=0');
45+
test('--inspect-brk=127.0.0.1:0');
46+
test('--inspect-brk=localhost:0');

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.