8

I have been playing with saving running Common Lisp images to save time upon restart and make the development more efficient. However, I am having a bit of a problem since when I run the following command in the Emacs/SLIME:

(sb-ext:save-lisp-and-die "rest-api-image" :purify t)

I get the following error. Clearly, it is complaining about seeing multiple threads. As far as I can see, these are not threads I created programmatically. Instead, these are Lisp- and Emacs-created. Is there a workaround here? Can the image still be saved?

Cannot save core with multiple threads running.

Interactive thread (of current session):
  #<THREAD "main thread" RUNNING {1000550853}>

Other threads:
  #<THREAD "Swank Sentinel" #1=waiting on:
       #<WAITQUEUE  {1004AB8003}>
     {1004AB4753}>,
  #<THREAD "control-thread" #1#
       #<WAITQUEUE  {1005BC54D3}>
     {1004D87F03}>,
  #<THREAD "reader-thread" RUNNING {1004D88063}>,
  #<THREAD "swank-indentation-cache-thread" #1#
       #<WAITQUEUE  {1004D980E3}>
     {1004D88183}>,
  #<THREAD "auto-flush-thread" RUNNING {10022FFDA3}>,
  #<THREAD "repl-thread" RUNNING {1002300003}>
   [Condition of type SB-IMPL::SAVE-WITH-MULTIPLE-THREADS-ERROR]
See also:
  SBCL Manual, Saving a Core Image [:node]
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
MadPhysicist
  • 5,401
  • 11
  • 42
  • 107

3 Answers3

7

The Cookbook has you covered: https://lispcookbook.github.io/cl-cookbook/scripting.html

The steps involved are:

(load "my-app.asd")
(ql:quickload :my-app)
(sb-ext:save-lisp-and-die #p"my-app-binary" :toplevel #'my-app:main :executable t)

So that's a possible Makefile target:

build:
    sbcl --load my-app.asd \
         --eval '(ql:quickload :my-app)' \
         --eval "(sb-ext:save-lisp-and-die #p\"my-app\" :toplevel #my-app:main :executable t)"

but doing so with asdf is portable. Add this to your .asdf system definition:

:build-operation "program-op" ;; leave as is
:build-pathname "<binary-name>"
:entry-point "<my-package:main-function>"

and then

(asdf:make :my-package)

To build a web app, with its web server, is one step more.

To parse command line arguments, catch a C-c, put everything on CI, see the Cookbook !

ps: if you need to try things out in a bare sbcl repl, have a look at cl-repl, or even sbcli, they're better than rlwrap sbcl.

Ehvince
  • 17,274
  • 7
  • 58
  • 79
5

The typical way to save an image is to start SBCL from the command line (not from within emacs for SLIME), load what you want present in the image, and immediately save the image. That ensures that there's no state or threads established by SLIME or other running processes/threads present when trying to save.

I typically write a short Lisp file to do it, and the final form has the call to save-lisp-and-die.

Xach
  • 11,774
  • 37
  • 38
1

If I remember correctly I had similar error and I managed to still save the image. I used the package trivial-dump-core.

It guides you to go to buffer *inferior lisp* in Emacs and running the expression (trivial-dump-core::sbcl-dump-image-slime "sbcl-slime").

reflektoin
  • 34
  • 3