I could use a sanity check. I've been trying to track down a problem with either mod_lisp (for apache 2.0) or TBNL. Since I was not able to isolate my problem, I decided to revert back to Apache 1.3 and mod_lisp 2.33 (for Apache 1.x). The problem is that I think I'm seeing some odd behavior and was hoping someone else could confirm.
In a nutshell, I added a simple print statement to APACHE-LISTEN in TBNL's modlisp.lisp file so I would know when this function was being invoked. I also added print statements before each significant line in that function so I could see what the heck was going on. Here is my version of that function:
(defun apache-listen (*apache-stream* command-processor &rest args) "Listens on *APACHE-STREAM* for commands from mod_lisp. Packages the command using GET-APACHE-COMMAND and passes it to the COMMAND-PROCESSOR function (which is PROCESS-APACHE-COMMAND). ARGS are ignored. Designed to be called by a KMRCL:LISTENER object." (declare (ignore args)) (format t ">>>>>>> Opening stream~%") (force-output) (let ((*close-apache-stream* t)) (unwind-protect (loop for *apache-socket-usage-counter* from 0 for command = (debug-value *command* (get-apache-command)) while command do (cond ((ignore-errors (format t ">>>>>>> Processing command ~A~%" (subseq command 0 3)) (force-output) (funcall command-processor command)) (ignore-errors (format t ">>>>>>> Flushing stream cuz no errors occurred for ~A~%" (subseq command 0 3)) (force-output) (force-output *apache-stream*))) (t ;; if an error occured during processing of ;; COMMAND we close this particular connection ;; to Apache (ignore-errors (format t ">>>>>>> Closing stream cuz error occurred for ~A~%" (subseq command 0 3)) (force-output) (setq *close-apache-stream* t)))) until *close-apache-stream*) (ignore-errors (format t ">>>>>>> Closing stream - no more commands~%") (force-output) (kmrcl:close-active-socket *apache-stream*)))))
Now, back in Apache 1.3 world, I hit a webpage that invokes the mod_lisp handler and thus TBNL. I see the opening, processing, and flushing messages. The next time I hit the page (30 seconds later), I see the same thing again. I never see a closing message, and a look at 'netstat -an | grep 3000' indicates that another socket has been allocated and is in a connected state. I repeated this process for a few minutes and got up to 6 connected sockets without ever seeing a closing message. If a subsequent hit comes close enough, then it will reuse the socket and I'll only see a processing and flusing message (no opening message).
I'm using SBCL (with multithreaded support). I'll continue debugging in the meantime and I'm going to start with fresh copies of everything to make sure I have not inadvertently affected things while debugging my original problems with Apache 2.x (which still appear when I use Apache 1.x).
I'll summarize those problems as well (as I think they may be related), essentially, I have a web page that has three stylesheets included in it (and are processed by TBNL as well), so basically, TBNL receives 4 requests in a fairly short amount of time. After adding debugging code to the mod-lisp.c Apache module, I've confirmed that mod-lisp sends the 4 requests to TBNL. Unfortunately, mod-lisp never receives any headers from TBNL for the last request although I've seen TBNL send them (I just didn't realize until now that they were probably going over different sockets).
In any case, I've been banging my head all day, I need a break, but it would be appreciated if someone could either confirm or deny the opening of multiple sockets while never closing any of the old ones. Its easy to see via a 'netstat -an | grep 3000' (or whatever port you run it on).
Thanks, Pete
I can confirm this behaviour with AllegroCL. This is obviously not what was intended. Unfortunately, I will be out of town until next week so I won't be able to investigate this further until then.
Cheers, Edi.
On Fri, Jul 16, 2004 at 02:40:19AM +0200, Edi Weitz wrote:
I can confirm this behaviour with AllegroCL.
Good! At least I'm not going crazy then!!
This is obviously not what was intended. Unfortunately, I will be out of town until next week so I won't be able to investigate this further until then.
I'll continue poking around and see if I can find anything. Its helping me learn how to debug lisp applications!
Thanks, Pete
On Thu, Jul 15, 2004 at 05:22:52PM -0400, pete-tbnl-dev@kazmier.com wrote:
In any case, I've been banging my head all day, I need a break, but it would be appreciated if someone could either confirm or deny the opening of multiple sockets while never closing any of the old ones. Its easy to see via a 'netstat -an | grep 3000' (or whatever port you run it on).
Upon further thought, isn't this behavior to be expected? I.e. as requests come into Apache, and Apache dispatches them to one or more of its children (processes/threads), doesn't each child via the mod_lisp handler create its own connection to TBNL on port 3000? And since Keep-Socket is "1", this is the reason why I never see any of the sockets closing. Thus, I should expect to see a socket for every child Apache process/thread, right? Or does mod_lisp make sure the same socket is used for all cases? This does not appear to be the case as I do see TBNL accept more than one connection on port 3000. Obviously, I'm not very familiar with the Apache API or mod_lisp.
Back to my original problem, I'm still a little confused as to why I can't get a simple page that includes 3 style links (irrelevant I suspect other than it does cause multiple requests to occur in a very short amount of time perhaps on different sockets from the client) in it to load properly under any combination of mod_lisp, TBNL and lisp implementation. I've tried using SBCL, CMUCL, Apache 1.x (w/ modlisp-2.33), Apache 2.x (w/ modlisp for 2.x Apache). The symptom is the same, the web browser just sits there and hangs until the mod_lisp module times out reading from TBNL.
Debugging the mod_lisp module seems to indicate that mod_lisp just sits there waiting for a response from TBNL. This seems to only occur for one of the four initial requests that it sent to TBNL (one of the style links). My only guess is that perhaps TBNL is somehow writing its response to the wrong *apache-stream* as mod_lisp handler does open multiple connections to TBNL on port 3000. I'm new to lisp and I'm not quite sure how special variables work in a multithreaded app or one that uses the CMUCL event loop.
I look forward to your return Edi for some enlightenment! :-)
Thanks, Pete
Hi Pete!
On Fri, 16 Jul 2004 12:31:07 -0400, pete-tbnl-dev@kazmier.com wrote:
Upon further thought, isn't this behavior to be expected? I.e. as requests come into Apache, and Apache dispatches them to one or more of its children (processes/threads), doesn't each child via the mod_lisp handler create its own connection to TBNL on port 3000? And since Keep-Socket is "1", this is the reason why I never see any of the sockets closing. Thus, I should expect to see a socket for every child Apache process/thread, right? Or does mod_lisp make sure the same socket is used for all cases? This does not appear to be the case as I do see TBNL accept more than one connection on port 3000. Obviously, I'm not very familiar with the Apache API or mod_lisp.
See the recent postings by Marc and myself. You've obviously found a bug in mod_lisp which is fixed now.
Back to my original problem, I'm still a little confused as to why I can't get a simple page that includes 3 style links (irrelevant I suspect other than it does cause multiple requests to occur in a very short amount of time perhaps on different sockets from the client) in it to load properly under any combination of mod_lisp, TBNL and lisp implementation. I've tried using SBCL, CMUCL, Apache 1.x (w/ modlisp-2.33), Apache 2.x (w/ modlisp for 2.x Apache). The symptom is the same, the web browser just sits there and hangs until the mod_lisp module times out reading from TBNL.
Debugging the mod_lisp module seems to indicate that mod_lisp just sits there waiting for a response from TBNL. This seems to only occur for one of the four initial requests that it sent to TBNL (one of the style links). My only guess is that perhaps TBNL is somehow writing its response to the wrong *apache-stream* as mod_lisp handler does open multiple connections to TBNL on port 3000. I'm new to lisp and I'm not quite sure how special variables work in a multithreaded app or one that uses the CMUCL event loop.
I look forward to your return Edi for some enlightenment! :-)
If it's not confidential then maybe you can just send me your code and I'll have a look at it. I currently don't have an idea what's the problem might be.
As for special variables: Although there's no standard for that there seems to be an agreement that every process/thread has its own set of bindings for special variables, i.e. if you do
(let ((*foo* ...)) ...)
within a thread and *FOO* is a special variable then within the body of the LET form the thread is manipulating its "private" version of *FOO* which is distinct from the value other threads have access to.
This is what happens in TBNL because of this line:
(defun apache-listen (*apache-stream* command-processor &rest args) ...)
When APACHE-LISTEN is called, the special variable *APACHE-STREAM* is bound. That would be equivalent to:
(defun apache-listen (apache-stream command-processor &rest args) (let ((*apache-stream* apache-stream)) ...))
If you haven't done so you might want to look at
http://cl-cookbook.sourceforge.net/process.html
which is about LispWorks but is nevertheless a pretty good general introduction to multi-processing in CL.
Cheers, Edi.
PS: TBNL (via KMRCL) doesn't use CMUCL's event loop but rather CMUCL's multi-processing facilities. It will therefore only work on x86 machines (unless you use other CL implementations, of course).
On Mon, Jul 19, 2004 at 12:57:22AM +0200, Edi Weitz wrote:
See the recent postings by Marc and myself. You've obviously found a bug in mod_lisp which is fixed now.
Yes, I can now confirm that all is well when working under Apache 1.3, mod_lisp 2.35, SBCL, and TBNL. My previous problem, which spawned this topic, appears to have been resolved. Pages are now loading correctly without incident.
Thanks for your help!! Now I just have to wait for an Apache 2.x module. Perhaps I'll take a stab at it when I finish my TBNL project, in the meantime, I'll just proxy between Apache 2.x and Apache 1.x.
As for special variables:
Thank you for the detailed explanation on special variables and multi processing environments.
Pete