Closed Leftbower closed 1 year ago
Being able to connect from VS Code, to the point where the callstack pane shows a listing of JVM thread names, indicates everything booted up fine, so that is a promising sign of life.
The unverified breakpoint issue could be a bug, but it could also be that the classfiles associated with the particular sourcefile in question hasn't been loaded by lucee yet, or that precompiled classfiles cached from previous non-debug server runs are being reused. The latter case sounds likely in a non-containerized setup. Deleting the class cache to force recompilations might be helpful; to troubleshoot, you could javap $someClassFile | grep -i "compiled from"
some of them, if they don't have anything (or it's not an absolute path) then they are definitely from previous "non-debug" runs, and luceedebug can't do anything interesting with them.
I deleted all precompiled classfiles to no avail. I then did a fresh install of the server to make sure I didn't miss any and same issue.
One thing I noticed though is that when I try to get into the Lucee admin, it blows up wit this error:
lucee.runtime.exp.NativeException: luceedebug/coreinject/DebugManager
at application_cfc$cf.newInstance(/admin/Application.cfc)
at lucee.runtime.component.ComponentLoader.initComponent(ComponentLoader.java:632)
at lucee.runtime.component.ComponentLoader._loadComponent(ComponentLoader.java:556)
at lucee.runtime.component.ComponentLoader.loadComponent(ComponentLoader.java:448)
at lucee.runtime.listener.ModernAppListener._onRequest(ModernAppListener.java:116)
at lucee.runtime.listener.MixedAppListener.onRequest(MixedAppListener.java:44)
at lucee.runtime.PageContextImpl.execute(PageContextImpl.java:2493)
at lucee.runtime.PageContextImpl._execute(PageContextImpl.java:2478)
at lucee.runtime.PageContextImpl.executeCFML(PageContextImpl.java:2449)
at lucee.runtime.engine.Request.exe(Request.java:45)
at lucee.runtime.engine.CFMLEngineImpl._service(CFMLEngineImpl.java:1216)
at lucee.runtime.engine.CFMLEngineImpl.serviceCFML(CFMLEngineImpl.java:1162)
at lucee.loader.engine.CFMLEngineWrapper.serviceCFML(CFMLEngineWrapper.java:97)
at lucee.loader.servlet.CFMLServlet.service(CFMLServlet.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at org.cfmlprojects.regexpathinfofilter.RegexPathInfoFilter.doFilter(RegexPathInfoFilter.java:47)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:67)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176)
at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:405)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:67)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at runwar.undertow.SSLClientCertHeaderHandler.handleRequest(SSLClientCertHeaderHandler.java:144)
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:275)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:79)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:134)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:131)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:255)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:79)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:100)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:391)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:852)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449)
at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1282)
at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.NoClassDefFoundError: luceedebug/coreinject/DebugManager
... 61 more
The dreaded NoClassDefFoundError
. Some kind of classloader problem. Could you list your JDK and Lucee versions? Do you have any kind of bespoke classloading/OSGi setup?
Lucee 5.3.10+97
OpenJDK Runtime Environment Temurin-11.0.17+8 (build 11.0.17+8)
No bespoke classloading/OSGi setup... even tried with a new site with just an index.cfm
and get the above error when trying to load the Lucee admin.
Was able to repro and pushed a fix, if you do a fresh build it ought to be better. It seems that the admin portion of Lucee is its own isolated OSGi bundle and we weren't handling that properly.
OK, the new build fixed the Lucee admin OSGi error. Now just still have the unverified breakpoint issue. Updated extension to 2.0.3
As in, they just won't ever hit? Unverified in and of itself isn't bad, until you run the file and they still don't become verified. This could be a path mapping issue ... maybe a case (in)sensitivity thing ... you're on windows, yes?
Correct, they never become verified. I am on Windows.
My jvm args:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=bh.dev.local:9999
-javaagent:c:/dev/luceedebug/luceedebug.jar=jdwpHost=bh.dev.local,jdwpPort=9999,cfHost=bh.dev.local,cfPort=10000,jarPath=c:/dev/luceedebug/luceedebug.jar
And my launch.json
looks like this:
{
"type": "cfml",
"request": "attach",
"name": "test",
"hostName": "bh.dev.local",
"port": 10000
}
My hosts
file has this:
127.127.0.33 bh.dev.local
This shouldn't affect your outcome, since you're already able to connect, but you may want to use this, instead, to simplify the JVM args:
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=localhost:9999
-javaagent:c:/dev/luceedebug/luceedebug.jar=jdwpHost=localhost,jdwpPort=9999,cfHost=bh.dev.local,cfPort=10000,jarPath=c:/dev/luceedebug/luceedebug.jar
@softwareCobbler may correct me if I'm wrong, but I don't think there's any reason a lay user should change address
/jdwpHost
from localhost
, so consider that hostname as a literal. (It's for internal communication between the agent and JDWP, so no reason to tinker with it.)
I also had a member of my team (the only Windows user) who wasn't able to get things working. We put that on the shelf for a while, but I'm not sure we've gotten verification yet that luceedebug works on Windows.
I wonder whether the paths aren't matching based on case (as @softwareCobbler alluded to) and/or slash direction differences.
@Leftbower, I propose an experiment. Could you do the following?
index.cfm
your web root, what does writeDump(expandPath("."))
return?cd
return?Once you have that, we can try a pathTransforms
mapping at the root level, specify a breakpoint in your root index.cfm, then go from there.
Created a new, blank site in Commandbox.
Changed the above JVM to localhost as suggested. No change.
Both the expandPath
in index.cfm
and the cd
in Windows cmd are indentical (i.e. "C:\dev\apps\lbtest")
I do not have pathTransforms
setup in launch.json
because - as per above test - I didn't believe they were needed?
Thanks, @Leftbower.
Because those paths match (which isn't true of remote or containerized servers, of course), the pathTransforms
is ostensibly unnecessary.
No luck with a breakpoint in that simple site's index.cfm
, I suppose?
I wonder if the backslashes or colon are borking the mappings. Until WIndows support is troubleshot, I wonder if there's any hack you could try, like:
"pathTransforms": [
{
"idePrefix": "C:/dev/apps/lbtest",
"serverPrefix": "C:/dev/apps/lbtest"
},
]
Or something goofy like WSL paths.
Thanks for your help @jamiejackson.
Correct, no luck with the breakpoint in index.cfm
.
Added the pathTransform as suggested, but no luck there.
I don't think it's a matter of casing as Windows is generally case insensitve, but furthermore all of my paths are lowercased, so there're no differences? I assume that the fact the agent jar is being found and loaded up proves that, right? (e.g. the CALL STACK panel is populated)
Perhaps we Windows users are just destined to dump()
our way through debugging :-)
Correct, no luck with the breakpoint in index.cfm.
Darn.
I don't think it's a matter of casing as Windows is generally case insensitive.
I also don't think it's a matter of case.
assume that the fact the agent jar is being found and loaded up proves that, right?
Right, because you're using the lowercase c
and java doesn't seem to mind.
Perhaps we Windows users are just destined to dump() our way through debugging :-)
No way! You may just be the first Windows guinea pig. We'll get it sorted.
Just pushed some stuff to help debug path mapping issues. It looks like maybe there's some complications with how vscode sends out drive letters.
After connecting to the server, from the command pallet (I think pressing F1 brings it up), type "luceedebug show class and breakpoint info", it should look like:
It will open an editor pane with info like the following
Breakpoints luceedebug has:
(ide) d:\lucee-express\lucee-express-5.4.0.23-SNAPSHOT\webapps\ROOT\index.cfm:2 (unbound)
(server) d:\lucee-express\lucee-express-5.4.0.23-SNAPSHOT\webapps\ROOT\index.cfm:2 (unbound)
Files luceedebug knows about (all filenames are as the server sees them, and match against breakpoint 'server' paths):
/admin/resources/menu.cfm
...snip...
d:\lucee-express\lucee-express-5.4.0.23-snapshot\webapps\root\application.cfc
d:\lucee-express\lucee-express-5.4.0.23-snapshot\webapps\root\index.cfm
d:\lucee-express\lucee-express-5.4.0.23-snapshot\webapps\root\web-inf\lucee\context\application.cfc
d:\lucee-express\lucee-express-5.4.0.23-snapshot\webapps\root\web-inf\lucee\context\component.cfc
pageimpl.java
The trick is to get the paths (case-sensitively) to line up. In the above configuration, I couldn't hit index.cfm because "root
" is not the same as "ROOT
". I had to add a path transform like:
"pathTransforms": [
{
"idePrefix": "d:\\lucee-express\\lucee-express-5.4.0.23-SNAPSHOT\\webapps\\ROOT",
"serverPrefix": "d:\\lucee-express\\lucee-express-5.4.0.23-snapshot\\webapps\\root"
}
],
Of particular interest is that the editor offers a macro-like helper like "${workspaceRoot}
" as shorthand, but it was saying that the workspace was D:\...
, but then the inbuilt DAP server would push breakpoints with d:\...
, so there's plenty of room for case mistakes.
Nice addition! I've needed that kind of information a lot over the last couple weeks.
I saw you made a canonicalization change last night. Was that related to this ticket?
I was just able to get things working on Windows, and I'm not sure if it's because of your change or not.
CommandBox server.json
:
{
"name":"lucee@5.3.10.97",
"jvm":{
"args":[
"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=localhost:9999",
"-javaagent:C:/Users/jamie/projects/luceedebug/luceedebug/build/libs/luceedebug.jar=jdwpHost=localhost,jdwpPort=9999,debugHost=0.0.0.0,debugPort=10000,jarPath=C:/Users/jamie/projects/luceedebug/luceedebug/build/libs/luceedebug.jar"
],
"javaVersion":"openjdk11_jdk"
},
"app":{
"cfengine":"lucee@5.3.10.97"
}
}
VS Code launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"type": "cfml",
"request": "attach",
"name": "Attach to server",
"hostName": "localhost",
"port": 10000
}
]
}
Debug output:
Breakpoints luceedebug has:
(ide) c:\Users\jamie\projects\luceedebug\sample\index.cfm:5 (bound)
(server) c:\users\jamie\projects\luceedebug\sample\index.cfm:5 (bound)
Files luceedebug knows about (all filenames are as the server sees them, and match against breakpoint 'server' paths):
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\function\writedump.cfm
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\ajaximport.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\ajaxproxy.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\div.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\dump.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\layout.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\layoutarea.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\lucee\core\ajax\ajaxbase.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\lucee\core\ajax\ajaxbinder.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\lucee\core\ajax\ajaxproxyhelper.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\map.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\mapitem.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\mediaplayer.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-server\context\library\tag\window.cfc
c:\users\jamie\.commandbox\server\7d0c5a764415367927375b99ef8f97d1-lucee@5.3.10.97\lucee-5.3.10.97\web-inf\lucee-web\context\component.cfc
c:\users\jamie\projects\luceedebug\sample\index.cfm
cipage.java
componentpage.java
componentpageimpl.java
pageimpl.java
@Leftbower , @softwareCobbler confirmed that his recent commit addressed this kind of thing and I was able to debug on a Windows machine.
Please try again and report back with your debugging info if you're still having problems.
@jamiejackson, @softwareCobbler new update works - thanks so much for all of your efforts!
I'm struggling to understand the correct syntax to set this up in VSCode. I am using
Commandbox
with thehost-updater
module so each dev site runs on port 443 with its own hostname. My hosts file would look similar to this:In this setup, I'm unsure where to put what in the jvm args? Using the stock settings in the docs, but with my path to the jar, results in an error starting up the server:
agent library failed to init: instrument
I get closer when I replace "localhost" with my host file's hostname (e.g. "test1.dev.local"). The server starts and when I start the debug profile the "CALL STACK" panel fills up, but then I get the "unverified breakpoint" discussed in issue #18
I also tried replacing the
cfHost
(and corresponding "hostname" in the launch.json) to test1.dev.local, but suffer the exact same results.It would probably help if I better understood what "localhost" is meant to refer to in the
agentlib
address
as well as thejdwpHost
and also whatcfHost
should refer to when NOT in a dockerized setting?