In 7.0.0
, looks like the typeof v8debug
always returns undefined
. How to detect if the process is running in the debug mode?
Check out the discussion in https://github.com/nodejs/node/issues/7102.
@cjihrig That's useful to know, but I'd like to have a solution without that flag: just another way to know if the process is in the debug mode (maybe some environment variable which is set by the debugger or something like that)?
Thanks!
Why would you care whether the process is being debugged or not? To answer your question, there is no real way to determine if the debugger is active (that is future proof.)
@bnoordhuis There are some features I want to disable in the debug mode to make the debugging easier. That's pretty much it.
You can only divine it indirectly. For example, vm.runInDebugContext('Debug').scripts()
throws an 'illegal access' exception unless the debugger is active. It only works with some node.js versions and will likely stop working altogether in the future.
Another possible way to check for debug mode (asynchronously) is to simply try to bind to the debug port:
function isDebugging(cb) {
require('net').createServer().on('error', function(err) {
if (err.code === 'EADDRINUSE')
cb(null, true);
else
cb(err);
}).listen(process.debugPort, function() {
this.close();
cb(null, false);
});
}
@mscdex Thanks! I'd prefer a sync version, tho. Actually, isn't possible just to set an environment variable or a global (like before) when debugging?
@IonicaBizau Well, if you are adventurous and don't mind relying on a "private" API, here is a synchronous version of my above solution....
function isDebugging() {
var TCP = process.binding('tcp_wrap').TCP;
var tcp = new TCP();
var r;
function doBind() {
var err = tcp.bind6('::', process.debugPort);
if (err)
err = tcp.bind('0.0.0.0', process.debugPort);
return err;
}
doBind();
r = doBind();
if (r) {
tcp.close();
return false;
}
return true;
}
I think this has been answered. Closing.
@mscdex Thanks for that! :+1:
@mscdex That code returns true even another process is being debugged. Is there any way to tell if the current process is debugged?
It seems more simple way is to check execArgv. In DEBUG mode there should be 'debug' or 'inspect' word in argument's list.
const argv = process.execArgv.join();
const isDebug = argv.includes('inspect') || argv.includes('debug'));
See https://nodejs.org/api/inspector.html
Note that there is no special "debug mode". What you may detect is whether or not inspector WebSocket server is running. Another is if there's any inspector session connected (currently you can create the session through the WebSocket connection or by using the JS API). Currently you can detect ongoing session by trying to connect another one and then catching this exception - but this will most likely stop working down the line once concurrent sessions are supported.
@eugeneo Right, if inspection is initiated programmatically my method is useless, however if the project isn't a public library, so developers are fully in control of how debug can be initiated, then execArgv check would be sufficient.
As said @zurgul, checking process.execArgv
doesn't work if the process switched to debug mode after a regular launch:
process._debugProcess(pid)
I also thought about sending a request to:
http://localhost:${process.debugPort}/json/version
http://localhost:${process.debugPort}/json
but a 200 OK
response might come from another node process.
The only reliable solution to me is the one mentioned by @mscdex
here a promise variant (then usable with async/await) I wrote to authorize some actions (like running an eval) only if we are in debug mode
const REJECT = new Error('Action refused, The UI process is not in debug mode');
const authorize = () => new Promise((resolve, reject) => net.createServer()
.on(
'error',
({ code }) => ((code === 'EADDRINUSE') ? resolve() : reject(REJECT))
)
.listen(process.debugPort, function () {
this.close();
reject(REJECT);
})
);
It would be awesome if we could have a process.debugSession
or process.debugId
returning the debugger session id when active and null otherwise
Why would you care whether the process is being debugged or not?
One use case I ran into was to set the timeout for tests to infinity if I'm stepping through the code, instead of the test timing out after the 5-second default timeout limit.
Should this issue be reopened?
Why would you care whether the process is being debugged or not?
In my context, I have a side inspect protocol that must accept requests only if the process is in debug/inspect mode.
@dandv I'd love to see it reopened, I think the cost would be minimal to have it natively
There should definitely be a standard easy-to-use method to detect whether the process is running on debug mode or not. The most reliable solution at the moment seems to be to pass a flag initially, and spawn child processes with this flag if it also is present in the parent. This is annoying and should be unnecessary. There should also be an option when spawning children that enables inspect if and only if the parent is also in inspect mode.
pptr uses inspector
module to detect that process is running under inspection: code.
As @eugeneo mentioned it detects that some debugger can connect to process but not that debugger is connected right now.
I think we should do this - any strong opinions ?
The question "how to detect debug mode" is wrong though. The debugger (inspector) is always enabled.
A better question is "is a client attached" but that's still kind of the wrong thing to ask because a client might be tracing or profiling but not debugging.
"Has the Debugger.enable
protocol command been executed by a client yet" comes closest but even that doesn't necessarily mean the client is actively debugging - it might for example only be interested in uncaught exceptions.
@bnoordhuis there is some method of debugging that 99% of users use (myself included). I think that what's important is that there is a native way to easily detect that
So what definition of debugging is that? When stepping? When breakpoints are set? When the script is paused?
(You wouldn't be able to detect that last one, of course!)
As to your 99% argument: it's only a matter of time before people start opening issues complaining our naive new API doesn't work for their legitimate use cases. "Good enough" often isn't.
Not if in the docs you state that this works only if ... . Also, people
complaining about issues is expected for every feature and should even be
encouraged. It's not by any means a reason not to implement a feature lol
On Thu, Aug 15, 2019, 5:23 PM Ben Noordhuis notifications@github.com
wrote:
So what definition of debugging is that? When stepping? When breakpoints
are set? When the script is paused?(You wouldn't be able to detect that last one, of course!)
As to your 99% argument: it's only a matter of time before people start
opening issues complaining our naive new API doesn't work for their
legitimate use cases. "Good enough" often isn't.—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/nodejs/node/issues/9617?email_source=notifications&email_token=ADLB3ZDCYBIJDPR6GH2FCXDQEW3LFA5CNFSM4CWKRDX2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD4M4O2I#issuecomment-521783145,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADLB3ZBWKKBAAUKOBW4TIE3QEW3LFANCNFSM4CWKRDXQ
.
Not if in the docs you state that this works only if ...
I can tell you from almost 10 years of experience as a Node.js maintainer that it never works that way.
It's not by any means a reason not to implement a feature
A badly designed feature? For me that'd be plenty of reason.
The point still stands that the ask is poorly defined. You never answered what constitutes your definition of "debug mode."
Neither is it clear to me when it's relevant to know that. If it's to work around timing sensitive code, then make it less timing sensitive. What other reasons are there?
@nicszerman I understand you want this to happen but listen to Ben here. It is important that we detect the right thing and we expose an API that is not misleading:
inspector.url
only tells us if a debugger port is open. That is either node was launched with --inspect
or for example a user started Node without it and fired a SIGUSR1Debugger.enable
. Debugger.enable
or SIGUSR1
followed by it at any point for any reason.What I'd like see core expose (names and functionality obviously subject to bikeshed):
inspector.isEnabled()
- basically inspector.url() === undefined
but without people relying on that so we can change/move inspector.url
more easily and for a clearer method.inspector.on('enabled'
when inspector isEnabled changes to true
- for example when a user fires SIGUSR1 or calls inspector.open
.inspector.on('attached'
- not sure how to do this technically (do we get a notification when someone connects to the socket?) .inspector.on('debugging'
when someone fires a Debugger.enable
or Debugger.disable
This will only expose the capabilities from core and let users decide what's best for their apps on their own rather than us exposing an incomplete API that hides capabilities.
@nodejs/inspector @bnoordhuis wdyt?
That's certainly closer to what I had in mind.
There is a practical snag however. Right now our inspector glue code doesn't interpret protocol messages at all, it just passes them to and from the inspector backend (i.e., V8.)
We don't want to be in the business of parsing/interpreting them because that's very fragile. The protocol changes frequently and even the wire format is in flux. Chromium is switching from JSON to a binary format for efficiency reasons.
In order for your proposal to work, V8's C++ inspector API would need to grow a number of new methods and callbacks. That requires cooperation from the V8 team and someone willing to do the work.
Whether the effort involved is proportional to the payoff remains to be seen. I'm not volunteering at any rate. ^^
@nodejs/v8 @hashseed is this something you are willing to expose? ^
@bnoordhuis as far as I know the binary stuff has stopped because it didn't actually improve performance but I am sure I am not updated.
I would certainly be possible for every inspector domain to expose an isEnabled
command which returns true or false. However, I fail to see the use case here. It sounds to me that that approach would provide way too much information or granularity than what is asked here.
@hashseed basically, I want to have a different behavior when the debugger is enabled (for example in order to emit less optimized but easier to debug code).
My use case of this feature is that I want to use a different log level when debugger is present. Detecting debuggers by bind
or argv
works but not universal. Hope there will be an official way to do it.
@bin-y That sounds reasonable.
A generic isDebugEnabled()
check might be too expensive to wrap around every log statement but a way to detect that console.log()
and friends are being redirected to the inspector should be feasible and is probably good enough for your use case?
Can you open a new issue and link back to this one?
Hi @bnoordhuis ,
A generic
isDebugEnabled()
check might be too expensive to wrap around every log statement
I agree with your opinion and I was not meant to do that. I didn't notice the inspector.url
way by the time I sent the commit. I'm now configuring log level only once on the initializing stage of my script by using inspector.url to check debuggers.
but a way to detect that
console.log()
and friends are being redirected to the inspector should be feasible and is probably good enough for your use case?Can you open a new issue and link back to this one?
If I need to change log level dynamically in the future, I'll try your idea by checking console._stdout.constructor
or open a new issue about this. Thanks.
Most helpful comment
It seems more simple way is to check execArgv. In DEBUG mode there should be 'debug' or 'inspect' word in argument's list.