Hi Rick,
I've been having some fun trying to chase down some of my application errors and in the process noticed this in the call stack:
Level: 2
Method: .processhit
Source: wwserver.prg at line 719
Code: this.ErrorMsg("Fatal Server Startup Error", "<p>The server failed to load on startup in the
<b>" + this.Class + ".OnLoad()</b> method. " +
"Please fix the following error in the server startup code.</p>" +
this.cErrorMsg)
Level: 1
Method: .processhitbinary
Source: wwserver.prg at line 803
Code: ENDFUNC
(The full call stack is 8 levels deep.) Then I thought that looks a little odd so let's go look at wwserver. In processhit, there's a WITH...ENDWITH, and at line 770 there's a RETURN, which I was told is a nice way to generate C5 memory errors. I don't think this is related to my application error but thought I should share. OTOH maybe this is the root cause...
Yeah I don't think that's what the problem is either, but after you said that I actually went in and removed the WITH
statement. I hardly ever use so I was actually surprised to find it in wwServer.prg
.
I don't think it causes a problem because every single Web Connection request goes through that WITH
statement, so if there was a problem we'd know it pretty quickly. The RETURN
in the middle there is for error handling which is the fallback error handler, so if code ends up there, things are usually pretty dire to begin with. That thing only fires during startup or if a request came in and has some consistency error that it fails to route to a process class. IOW - that should be very rare to begin with.
IAC - the WITH
there is gone, so if it was potentially an issue - no more. 😄
+++ Rick ---
I'll update my local copy and keep an eye on my error reports for a bit.
I pushed a build to my staging environment and triggered an error. It got rid of the odd stuff in the call stack.
Level: 2
Method: .processhit
Source: wwserver.prg at line 714
Code: IF (this.lStartupError)
Level: 1
Method: .processhitbinary
Source: wwserver.prg at line 799
Code:
I don't think that's the same type of error.
The first error looks like it's caused by a startup failure. Something in .OnLoad()
failed and crashed. So if you're going to duplicate, put an error into .OnLoad()
and then see what it looks like.
+++ Rick ---
Yeah, I have to take a deeper dive in to this... If I turn on debug, will that provide more information or do I need to subclass wwserver?
Your server class is a subclass of wwServer
so you can intercept whatever you need to there. If startup fails you should know - if you don't have enough information there, then output more info with THIS.Trace() which writes into a text file log you can examine.
+++ Rick ---
Since that error is coming from processHit where is the right place to put in a trace call? And would I add something like this?
IF NOT EMPTY(this.cErrorMsg)
this.trace(this.cErrorMsg)
ENDIF
Anywhere really. If the error message is correct and points at the actual code then it seems there's some problem with the startup flag.
Questions you should ask:
- Does this occur on the first hit? If so likely a startup error caused by
OnLoad()
- or - there's some versioning problem that
lStartupError
is not defined (old version?)
If that's not it, then put trace commands into the code to see how far you get into the method. Put one at the start, in the middle and end and see if you get through, or if it fails, see where it failed. From there you can drill in more. As you pin it down, log out information about the request, the values and so on. If it fails, wrap an exception handler around the code and see what you get in the manual exception. etc. etc. etc.
+++ Rick ---
Thanks. Of course, this is only happening in production...
Sure, but you can do the logging in production, that's the whole point.
On the dev machine you can just set a break point anywhere including startup code.
My guess it's some environment issue on startup - connection failing, permissions not there to access a file - something along those lines. You need to isolate the source and from there wrap the code in question and look at the exception default which you can write out - at the point of failure.
The problem with FoxPro is that it does such a shitty job preserving the call stack and stack specific runtime information. It helps if you ship your app compile in Debug as then at least you should get source code lines that hoepfully are at least close (they never seem to be right on the line for whatever reason).
++ Rick ---