1

I have followed all the steps in the cl-cookbook. I created a webapp project with quickprojects.

I have my .asd file:


(asdf:defsystem #:serve
  :description "Describe server here"
  :author "Your Name <your.name@example.com>"
  :license  "Specify license here"
  :version "0.0.1"
  :serial t
  :depends-on (#:hunchentoot)
  :components ((:file "package")
               (:file "serve"))
  :build-operation "program-op" ;; leave as is
  :build-pathname "serve"
  :entry-point "serve:main")


I have the lisp server file:

(ql:quickload "serve")
(in-package #:serve)


(defvar *acceptor* (make-instance 'hunchentoot:easy-acceptor :port 4242
                  :document-root #p"www/"))


;; start the server
(defun main ()
  (hunchentoot:start *acceptor*))

(setf (hunchentoot:acceptor-document-root *acceptor*) #p"./www/")

I have the package.lisp file:


(defpackage #:serve
  (:use #:cl)
  (:export main))

Finally, I have the make file for creating the executable:


build:
        sbcl \
         --eval '(load "serve.asd")' \
         --eval '(ql:quickload "serve")' \
         --eval "(asdf:make :serve)" \
         --eval '(quit)'

When the executable comes out after running make build, and I run it with ./serve.... nothing happens.

My expectation is that the server will run as it does when i run it with emacs.

My goal is to send the executable to the server to run it. Not sure if that is the best deploy process. But at the moment, it's good enough for testing.

Even more worrying is that when I send the executable to my ubuntu server, i get a zsh error. This only happens when I build it on my MacOs and send it to ubuntu. However, when I build on ubuntu (i rebuilt the project on the VM to test it), the executable does nothing.

Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
Vinn
  • 1,030
  • 5
  • 13
  • The webserver is started on background, and nothing waits for it so the app finishes. Related issue and solution: https://stackoverflow.com/questions/48103501/deploying-common-lisp-web-applications & https://stackoverflow.com/questions/72545293/common-lisp-web-app-started-in-systemd-compilation-unit-aborted-caught-1-fata?rq=1 – Ehvince Nov 11 '22 at 08:38
  • Some use `(sleep most-positive-fixnum)` or the `join-thread` trick. – Ehvince Nov 11 '22 at 08:42

1 Answers1

3

Your main problem is that your main function immediately returns, terminating the server as soon as it is started. I would change it as follows:

;; start the server
(defun main ()
  (hunchentoot:start *acceptor*)
  (sb-impl::toplevel-init))

When you rebuild and run ./serve, a simple prompt appears *, which is the SBCL REPL. Your webserver is running in another thread. This can be useful to query the state of the server, or debug. You can even start a Swank server to connect and hack the code while it runs. When you want to stop the server, press CTRL-D to exit the REPL and the program terminates.

You can imagine other mechanisms to keep the server running until everything stops (like joining all threads, etc.) but this should be enough for testing.

Also,

(ql:quickload "serve")

This is not required in serve.lisp, the code by itself should not contain invocations to ql:quickload, it is sufficient to do it in the build command.

Likewise:

--eval '(load "serve.asd")' \

can be removed if you put your .asd file in a place where quicklisp can find it, see 4.1 Configuring ASDF to find your systems.

coredump
  • 37,664
  • 5
  • 43
  • 77
  • What do you mean by `immediately returns, terminating the server`? Is that because it's an executable? because when i run in the repl it doesn't terminate. Thanks again coredump. – Vinn Nov 09 '22 at 17:25
  • 1
    the hunchentoot:start function starts a thread. When you execute this from the repl, the repl continues its interactive loop while the server runs in the background. Giving a toplevel argument to save-lisp-and-die replaces the default toplevel by a custom function. When that function quits, the program terminates. So here if you don't suspend the main function somehow (you could just call read-line for example), it immediately quits. The line I added reintroduces the usual REPL – coredump Nov 09 '22 at 19:42
  • I want to clarify 2 things here... the expression you added to the main function, it's job is to have something else return rather than the server. And, by doing so, the server does not close on return. is that right? Also, can you explain how I would run the server (on port 4242 for example) and connect swank server to the hunchentoot server to hack at it? (I use slime+emacs btw) – Vinn Nov 10 '22 at 15:25
  • 1
    To start a Swank server and connect to it: https://lispcookbook.github.io/cl-cookbook/debugging.html#remote-debugging – Ehvince Nov 11 '22 at 08:37