fukamachi / clack

Web server abstraction layer for Common Lisp
MIT License
1.05k stars 86 forks source link

Clack with fcgi doesn't work on stdin #69

Open nbtrap opened 10 years ago

nbtrap commented 10 years ago

I can't get clack to do anything when passing :server :fcgi :fd 0 to CLACKUP.It works when I do a bare call to CL-FASTCGI::SERVER-ON-FD with a random callback function, but when I go through clack, the callback function is never called.

Any suggestions?

fukamachi commented 10 years ago

Don't specify :fd unless you'd like to use an existing socket to listen.

nbtrap commented 10 years ago

I understand that. In fact, the FastCGI spec says that the server is supposed to connect to the application with fd 0 already opened as a socket, on which the application then calls accept(2). It's precisely what I want to do, but it doesn't work.

nbtrap commented 10 years ago

Edit: It doesn't work when I use Clack. When I use just bare fastcgi, it works. Looking at the code, I can't figure out what substantial difference there is in the call(s) to fastcgi.

fukamachi commented 10 years ago

Write the code here. Does your Lisp implementation support threads?

nbtrap commented 10 years ago

Works:

(in-package :cl-nbtrap)

(defun app (req)
  (multiple-value-bind (status-code headers content)
      (funcall (get-handler-for req) req)
    (sb-fastcgi:fcgx-puts req
                          (with-output-to-string (s nil)
                            (when status-code
                             (format s "Status: ~D ~A~%" status-code (http-status-reason status-code)))
                            (loop for header in headers do
                                 (format s "~:(~A~): ~A~%" (car header) (cadr header)))
                            (format s "~%~A" content)))))

(defun get-handler-for (req)
  (declare (ignore req))
  #'generic-handler)

(defun generic-handler (req)
  (declare (ignore req))
  (values 200 '((:content-type "text/html"))
          (html/standard-page ("Coming Soon")
            (:h1 (:a :href "mailto:nbtrap@nbtrap.com") "Coming Soon"))))

(defun run-with-fastcgi (&optional load-path)
  (if load-path
      (sb-fastcgi:load-libfcgi load-path)
      (sb-fastcgi:load-libfcgi))
  (sb-fastcgi:simple-server #'app))

Doesn't work:

(in-package :cl-nbtrap)

(defun app (env)
  (declare (ignore env))
  `(200
    (:content-type "text/html")
    (,(html/standard-page
         ("Coming soon")
       (:h1 (:a :href "mailto:nbtrap@nbtrap.com" "Coming soon."))))))

(defun run-app (&rest args &key (server :hunchentoot) &allow-other-keys)
  (apply #'clack:clackup #'app :server server args))

The first example works with sb-fastcgi and cl-fastcgi. In the latter example, I call (run-app :server :fcgi :fd 0), which ends up calling CL-FASTCGI::SERVER-ON-FD, which is the same function that is eventually called in the working example.

Yes, I'm running a working threaded implementation.

fukamachi commented 10 years ago

In the latter example, I call (run-app :server :fcgi :fd 0), which ends up calling CL-FASTCGI::SERVER-ON-FD, which is the same function that is eventually called in the working example.

Could you tell me what happens when you call (run-app :server :fcgi :fd 0)?

nbtrap commented 10 years ago

So far as I can tell, control reaches __BEGIN__ but never reaches __END__:

(defun server-on-fd (func fd &key (flags 0))
  (fcgx-init)
  __BEGIN__
  (with-foreign-object (req 'fcgx-request)
    (fcgx-init-request req fd flags)
    (do ((rc (fcgx-accept req) (fcgx-accept req)))
        ((< rc 0) "ACCEPT ERROR")
      __END__
      (funcall func req)
      (fcgx-finish req))))
nbtrap commented 10 years ago

Other than that, I can't tell. I'm not getting any error message or entering the debugger.

nbtrap commented 10 years ago

Any idea what might be going wrong?

fukamachi commented 10 years ago

Honestly, I have no idea. The only difference is, Clack always makes a thread. Have you tried Clack.Handler.Fcgi with bt:make-thread deleted?

nbtrap commented 10 years ago

I believe I did.

If you can't figure it out, I may spend some more time on it. I want to write my web sites/apps in lisp, and this seems like the most viable option, but the shared hosting service I use doesn't let me run my own server. Fcgi is my only option at this point.