3

We have a set of Coldfusion applications that all extended various parts of an application base. I'll provide a bit of code and then explain the issues we are having and see if anyone can shed light on the best way to trouble shoot this:

In our "OnRequestStart" in the app.cfc we have the following line to initiate a user:

if(!structKeyExists(SESSION, 'user'))
SESSION.user = CreateObject("component","cfcs.ds_user");

Then in the ds_user.cfc we call it like so:

component extends="cas.cas_user" displayname="basic_user"{

The application and all its parts run just like they should. However, in a seeming random manner after a while, the application will crash and I have to restart ColdFusion Service to get it running again. The error I get is:

Could not find the ColdFusion component or interface cas.cas_user.

So, for whatever reason after a while, my application decides it cannot find the path to the parent component. The mapping for that cfc is in the application.cfc at the top as so:

THIS.mappings["/cas"] = "#ReplaceNoCase(currpath,ListToArray(THIS.name,'_')[1],'cas30')#assets\cfcs\";

I want to be sure to say this, the application works perfectly as designed for a random amount of time and then it cannot find the parent component and will not find it again until I restart the ColdFusion Service on the server.

I figure this is somehow a memory leak or something, but I have no idea where to start looking to troubleshoot the issue. We have 6 or so other applications that are extended in the same way and work fine and never crash, but this one does.

EDIT: To be more clear on the mappings. Our applications are located:

  • root.com/app1
  • root.com/app2

We created mappings to grab cfcs from app2 while in app1 using the method above. The method, while I believe sort of strange, does work in all of our applications.

EDIT: The correct mappings that display for a while are:

/cfcs - D:\www\app1\assets\cfcs
/templates - D:\www\app1\assets\templates
/cas - D:\www\app2\assets\cfcs
/common - D:\www\app3\assets\common_elements

However once the Application goes in "crashed mode", the dump reveals the mappings are as follows:

/cfcs - D:\www\app1\assets\cfcs
/templates - D:\www\app1\assets\templates
/cas - D:\www\app1\assets\cfcs
/common - D:\www\app1\assets\common_elements

And here is how those mappings are defined at the start of the Application.cfc:

currpath = GetDirectoryFromPath(GetCurrentTemplatePath());
THIS.mappings["/templates"] = "#currpath#assets\templates";
THIS.mappings["/cfcs"] = "#currpath#assets\cfcs";
THIS.mappings["/common"] = "#ReplaceNoCase(currpath,ListToArray(THIS.name,'_')[1],'gum')#assets\common_elements\";
THIS.mappings["/cas"] = "#ReplaceNoCase(currpath,ListToArray(THIS.name,'_')[1],'cas30')#assets\cfcs\";

THIS.name = digisign_CAAAFACBFDFFE or

name_var = (arrayLen(meta_array) >= 2) ? meta_array[arrayLen(meta_array) - 1] & '_' : 'root_';
THIS.name = name_var & right(reReplace(hash(getCurrentTemplatePath()), "[^a-zA-Z]","","all"), 64 - len(name_var));

Where could it be failing. It seems the replace statement isn't working and therefore the appname in the path is not being changed from app1 to app2 when setting the mappings. is it possible this is related to this error we are currently working through: http://forums.adobe.com/message/4657868#4657868 We have yet to apply the Update 4 patch on production. However this problem we believe was happening before CF10. And while we have this issue, it only cropped up recently. This application in question has been crashing like this for a long time.

EDIT: 1. I guess when I say "crash" I mean the application gets into a state, where it will not declare the mappings correctly until I restart Coldfusion. I assume the error in our code causes the crash. 2.This is usually where the issue occurs, when doing this check of the SESSION.user var. I believe it has happened as well, it decides it cannot find our datasource. This is rare. 3. At first I thought yes, but actually no, not that many. Throughout our apps we have several names for common mappings. cas common cfcs templates etc. However D:\www\cas is where the application domain.com/cas30 is located. However a legacy version of that app is located at domain.com/cas. The mapping /cas should go to D:\www\cas30\assets\cfcs and works. 4.We have a dev setup and this never happens. (I assumed it was a load issue which is why it doesn't happen on dev). However, our dev environment is structred as so:

D:\www\deva\app1
D:\www\deva\app2
D:\www\devb\app1
D:\www\devb\app2
  1. What we do (which I think is stupid) is we have a file located not in the same dir as the current app. This file is called application_base.cfc. All of the application.cfcs in the other applications extend from this application_base.cfc. They are not extended from other Application.cfc files. (hope that makes sense) In application_base is a init, onrequeststart, and an onerror. I'll post the App.cfc below. Also some setting are read from XML files both in the application base (to determine environment stuff) and at the application level. However we thought that might be causing the issue so the previous developer removed the xml file at the application level. 6.Yes. I'll post the app.cfc and the appbase.cfc so you can view both.
  2. By reinitialize you mean call onapplicationstart or something. Not that I know of.
  3. A few applications we have do:

    currpath = GetDirectoryFromPath(GetCurrentTemplatePath()); app_path = ListToArray(currpath,'\'); THIS.name = app_path[ArrayLen(app_path)];

This one does:

meta_array = ListToArray(GetMetaData(this).name,'.');
name_var = (arrayLen(meta_array) >= 2) ? meta_array[arrayLen(meta_array) - 1] & '_' : 'root_';
THIS.name = name_var & right(reReplace(hash(getCurrentTemplatePath()), "[^a-zA-Z]","","all"), 64 - len(name_var));

A few others do this as well. Not sure if it was two different developers or something, but that is the way it is.

Once the app fails, it fails until I restart coldfusion. The app requires login from the domain.com/app page, so (not saying it cant change from request to request) but the request location is always the same where it's failing.

God I wish it wasn't this complex. I recently pulled our current CMS off of alot of this crazy stuff, but we have 7 or 8 applications that are so intertwined with each other and designed to work in dev/prod environments with different paths, its sometimes hard to tell what I can remove and what I can't.

I thought I tried dumping the applicationname from our error handler, but I thought it didn't work unless passed in. I passed through the mappings so I could see them which is how I know digisign is not changing to cas30 like it should in "crash" mode.

I think all the dynamic mappings were so the original developer could just use the same app.cfc template without changing anything. He liked to do stuff like var a = (b) ? (a-c) ? a-f+b : (a+b) ? d : d; : a; h; crap with no comments so it sometimes hard to just read the damn code let alone debug it.

EDIT

I feel like this issue and stackoverflow.com/q/14300915/1229594 issue may be related. I've posted some more details here as well: forums.adobe.com/message/5022377#5022377

Community
  • 1
  • 1
Leeish
  • 5,203
  • 2
  • 17
  • 45
  • Is the 'THIS.mappings["/cas"] in a method? If so, which? – Barry Jan 14 '13 at 12:43
  • No all of the mappings are at the start of the app.cfc file. Right after the curr_path is determined. It's like the server craps out and decides it all of a sudden can't find the paths. – Leeish Jan 14 '13 at 16:37
  • Do you think this is happening after the application timeout period? I have been fighting something similar for a while but under ColdFusion 9. http://stackoverflow.com/questions/12286622/when-the-onapplicationend-event-fires-it-can-no-longer-resolve-the-mappings-i-ha – Miguel-F Jan 15 '13 at 15:50
  • Not familiar with the application timeout period. You mean, when IIS shuts down worker processes after they are idle or something CF does with idle applications. Our sometimes happens during the day, but often at night. It "appears" to happen when our applications are busier. I just read your post, we don't do anything in application end. – Leeish Jan 15 '13 at 15:57
  • Try to dump your mappings when the application fails and see if they are different. – Leeish Jan 15 '13 at 16:04
  • Is there any pattern to how long before you can expect an error? For example, always at least 20 minutes after a restart or always within 2 days of a restart? – Steve Bryant Jan 18 '13 at 21:09
  • I'm still not clear where you are getting the error `Could not find the ColdFusion component or interface cas.cas_user.`. You mention in a comment below it's this line `currpath = GetDirectoryFromPath(GetCurrentTemplatePath());` but that line does not match the error being reported. I realize the referenced line may not be the problem and is just the result of another issue but I would like to know where in your code the referenced line is (which function). Could you please verify the code/line that is referenced with the error? – Miguel-F Jan 18 '13 at 22:31
  • My gut feeling is to suspect application namespace overwriting. i.e. another app is naming itself the same. Can you just hardcode the application names and cfc paths in each app for a day and see if the crash continues? – BKK Jan 18 '13 at 23:04
  • I'll try that. The app doesn't crash daily though. Sometimes a week, sometimes three, sometimes once a day. Seemingly random. I am currently in the process of cleaning up non-scoped variables which may or may not be related to these issues. – Leeish Jan 19 '13 at 00:20
  • I feel like this issue and http://stackoverflow.com/q/14300915/1229594 issue may be related. I've posted some more details here as well: http://forums.adobe.com/message/5022377#5022377 – Leeish Jan 25 '13 at 16:04

3 Answers3

1

First things first: why are you initialising session-oriented stuff in onREQUESTStart()? If you inited that in onSessionStart(), you'd not need to check for its existence every request, which - whilst trivial - is unnecessary overhead, and is simply the wrong code in the wrong place.

Secondly... you quote your error, but don't say where it's happening. Is it happening in that line in onRequestStart()?

If so, do me a favour: put a try/catch around it, and within that write the value of this.mappings to a log file, as well as the value of currPath. How is the value of that variable being derived, btw?

That said, I think if you just put that session.user init code in the right place, it'll solve your problem.

NB: frame this problem as almost certainly not a memory leak (ie: ColdFusion's fault), but your code doing something you did not anticipate (so... err... your fault ;-). This will help focus better on finding the problem. I'm not having a go at you, but "where is my code wrong" is a better approach than "it's probably something else". And more likely to be correct ;-)

Oh... and what version of CF are you on?

Adam Cameron
  • 29,677
  • 4
  • 37
  • 78
  • I did not create all of these applications, I am simply the current admin. The error happens in the onRequestStart at that line, yes. `currpath = GetDirectoryFromPath(GetCurrentTemplatePath());` – Leeish Jan 11 '13 at 22:04
  • CF10. I believe this was also happening in CF9, but I was not the admin at that point and I don't remember. I am 99% sure this isn't something that started with the CF upgrade. I was only assuming a memory leak because it happens after time, not right away. – Leeish Jan 11 '13 at 22:10
  • Fair enough. I'd schedule in some time to move that code & regression test though. Anyway, stick that debug logging in if you can. Do you have any Application.cfc inheritance going on, or is that the only one? – Adam Cameron Jan 11 '13 at 22:15
  • Our application.cfcs (in my opinion) are a bit messy, but this is one of the cleaner ones. I will post it as an edit for you to chew on. – Leeish Jan 11 '13 at 22:18
  • I've added the mappings dump as part of our error handler email. Next time the application crashes I will see what it says and possibly revisit this thread. – Leeish Jan 11 '13 at 23:06
  • Please do. I'm keen to know what the story is. – Adam Cameron Jan 11 '13 at 23:08
  • Did it again this morning. It does seem to happen first thing in the morning. Like maybe after a/some application(s) are ended and this one is starting back up. Is there a way to check if something like that is the cause? – Leeish Jan 18 '13 at 15:16
  • You can stick something in each of onApplicationStart() and onApplicationEnd() to log that sort of activity. And then correlate when various apps start and stop I guess? And, sorry, didn't not see you'd updated the question with the data I asked for. Will look at it over the w/end. – Adam Cameron Jan 18 '13 at 17:24
  • Thank. To me `#ReplaceNoCase(currpath,ListToArray(THIS.name,'_')[1],'cas30')#assets\cfcs\` it would have to fail here. It's not replacing the current app name with cas30. Which would "have" to mean the replace isn't working. But if none of the code changes, what gives. This is so strange. One thing to note is we have a mapping in CFAdmin. Our App.cfc extends a appbase.cfc located elsewhere. However no mappings are set there. – Leeish Jan 18 '13 at 17:37
  • OK. Put the strings you're going to be using for the latter two mappings into a variable, and have some code that checks if that variable still starts with `currPath` after the replace, and if so: dump a bunch of stuff to a log, eg a struct containing CGI.script_name, CGI.http_host, CGI.query_string (so you know what was being requested), the `this` scope, [anything else that might help you identify why `ListToArray(THIS.name,'_')[1]` doesn't return what you are expecting it to return). CF will be doing exactly what you're asking it to... you're just asking it to do the wrong thing, sometimes. – Adam Cameron Jan 19 '13 at 18:48
  • How would the current path put it in a state where it can no longer run? – Leeish Jan 19 '13 at 23:28
  • Well if I knew that,I'd just tell you! ;-) You've got so much dynamic code that works on the basis of presupposing a bunch of factors,it's hard to say what's going on. I suspect that Application.cfc is being called via a request "path" you're not expecting,so the various values that need to be "just right" for all that code to work aren't...what you expect.I always start these exploratory exercises from the POV that the code is WRONG,not that "oh that's weird: the code is right but it doesn't work for some other reason". It gets your brain in the right place to objective about troubleshooting. – Adam Cameron Jan 19 '13 at 23:36
  • I'm going to hard set the app name this week and see what happens. All I am wondering is, those mapping are set with each request. They are read at the top of the app.cfc, outside of any methods. So... What can happens if my files don't move, to all of a studen have each request not work. Makes no sense. I am going to run more tests based on everyone's suggestions and see what happens. – Leeish Jan 19 '13 at 23:38
0

Take a look at this and see if it's relevant to your problem. https://github.com/Mach-II/Mach-II-Framework/wiki/Application-Specific-Mapping-Workaround

If not, then it could have something to do with application specific mappings of the same name, on the same CF server, with those applications having different application names.

Adrian J. Moreno
  • 14,350
  • 1
  • 37
  • 44
  • All of our applications run fine. This one runs fine for a while, and then dies. I don't see anything could be "wrong" with our mappings. We have tons of cfcs all mapped throughout our applications and this is the only application with an issue. Thanks. – Leeish Jan 11 '13 at 22:09
0

Some questions:

  1. Are you assuming the crash is being caused by the code error, or that the code error is occurring because of the crash?

  2. Is the instantiation of the session user the only line of code that you see these path errors?

  3. Do you have any physical directories in your app that have the same name as the mapping names?

  4. Does this occur in any other environments (dev/test)? Is this a clustered environment?

  5. Are there multiple Application.cfc files extending this same Application.cfc?

  6. Is there any code that is directly calling Application.cfc methods?

  7. Are there any bits of code that cause the application to reinitialize itself?

  8. What is determining the meta_array that is being used to derive the application name?

A few observations:

It seems to me that the application name is getting changed or that some other application is overwriting with the same name. This doesn't seem far-fetched as there's an awful lot of dynamic naming going on here. Starting with the application name, it's dependent on the current template's physical location, which could be different from request to request, depending on how the app routes requests. If the current template varies, the application name will vary, and cause the other app-specific mappings to change, which would cause a cascading effect to all the other mappings that use the app name to determine the physical location of those mappings.

Which begs the question: Why is all this dynamic evaluation of the application name and mapping locations even necessary? Can it be simplified or hard-coded? Can you instead use a server mapping? If it doesn't have to be this complex, simplifying it to its barest essentials will help troubleshooting and may clear up the issue entirely.

Finally, can you verify that the application name during normal operation is the same application name being referenced when the errors are occurring?

  • If they are different, then something is causing the application to execute within a different context (see my initial questions above for clues). A sudden change in the application name would invalidate any existing sessions and force the session user instantiation code to re-run. And because the user component paths are based in part on the application name, the paths may no longer be correct.

  • But if the application names are the same between normal operation and crash mode, then most likely the currpath variable is being affected by some part of the application being executed in a different physical path than expected. Since currpath is directly used in determining the rest of the mappings, that could certainly explain why an unexpected path could cause the component to go missing.

  • Because there are so many variables going into deriving these names, you would be well served to log those variables during normal operation and during crash mode. You'll want to see

    GetCurrentTemplatePath()
    GetDirectoryFromPath(GetCurrentTemplatePath())
    THIS.name
    meta_array
    THIS.mappings
    

I suspect you'll find something significantly different in these variables when operating normally and when the crash/errors are occurring, and that difference should lead you closer to the answer.

imthepitts
  • 1,647
  • 10
  • 9
  • I'll try to answer these in my edit. These apps were not build by me, so it's hard to answer on the fly. – Leeish Jan 18 '13 at 23:56