Skip to content

Porting from CCL to SBCL

Arnold Noronha edited this page Nov 21, 2022 · 3 revisions

If you've been using the Screenshotbot Docker images, you'll notice on most recent updates, you might get a message that look likes this:

Unhandled BKNR.DATASTORE::INVALID-STORE-RANDOM-STATE in thread #<SB-THREAD:THREAD "main thread" RUNNING                                                                                                            
                                                                  {1001898273}>:                                                                                                                                   
  Condition BKNR.DATASTORE::INVALID-STORE-RANDOM-STATE was signalled.                                                                                                                                              
                                                                                                                                                                                                                   
Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {1001898273}>                                                                                                                                              
0: (SB-DEBUG::DEBUGGER-DISABLED-HOOK #<BKNR.DATASTORE::INVALID-STORE-RANDOM-STATE {1005220B53}> #<unused argument> :QUIT T)                                                                                        
1: (SB-DEBUG::RUN-HOOK *INVOKE-DEBUGGER-HOOK* #<BKNR.DATASTORE::INVALID-STORE-RANDOM-STATE {1005220B53}>)                                                                                                          
2: (INVOKE-DEBUGGER #<BKNR.DATASTORE::INVALID-STORE-RANDOM-STATE {1005220B53}>)                                                                                                                                    
3: (ERROR BKNR.DATASTORE::INVALID-STORE-RANDOM-STATE)                                                                                                                                                              
4: ((:METHOD BKNR.DATASTORE::ENSURE-STORE-RANDOM-STATE (BKNR.DATASTORE:STORE)) #<UTIL/STORE:SAFE-MP-STORE DIR: "/data/">) [fast-method]                                                                            
5: ((:METHOD BKNR.DATASTORE::RESTORE-STORE (BKNR.DATASTORE:STORE)) #<UTIL/STORE:SAFE-MP-STORE DIR: "/data/"> :UNTIL NIL) [fast-method]                                                                             
6: ((:METHOD INITIALIZE-INSTANCE :AFTER (BKNR.DATASTORE:STORE)) #<UTIL/STORE:SAFE-MP-STORE DIR: "/data/"> :MAKE-DEFAULT T) [fast-method]                                                                           
7: ((LAMBDA (SB-PCL::|.P0.| SB-PCL::|.P1.|) :IN "/app/launch.lisp") #<unavailable argument> #<unavailable argument>)                                                                                               
8: (UTIL/STORE:PREPARE-STORE)                                                                                                                                                                                      
9: ((LAMBDA NIL :IN SERVER:MAIN))                                                                                                                                                                                  
10: (SERVER/INTERRUPTS::CALL-UNWIND-ON-INTERRUPT #<FUNCTION (LAMBDA NIL :IN SERVER:MAIN) {1006E3ADEB}> #<FUNCTION (LAMBDA NIL :IN SERVER:MAIN) {1006E3AE0B}>)                                                      
11: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SERVER:MAIN) #<NULL-LEXENV>)                                                                                                                                                    
12: (SB-INT:SIMPLE-EVAL-IN-LEXENV (UNLESS (MEMBER "compile" (UIOP/IMAGE:COMMAND-LINE-ARGUMENTS) :TEST (QUOTE STRING=)) (SERVER:MAIN)) #<NULL-LEXENV>)                                                              
13: (EVAL-TLF (UNLESS (MEMBER "compile" (UIOP/IMAGE:COMMAND-LINE-ARGUMENTS) :TEST (QUOTE STRING=)) (SERVER:MAIN)) 6 NIL)                                                                                           
14: ((LABELS SB-FASL::EVAL-FORM :IN SB-INT:LOAD-AS-SOURCE) (UNLESS (MEMBER "compile" (UIOP/IMAGE:COMMAND-LINE-ARGUMENTS) :TEST (QUOTE STRING=)) (SERVER:MAIN)) 6)                                                  
15: ((LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) (UNLESS (MEMBER "compile" (UIOP/IMAGE:COMMAND-LINE-ARGUMENTS) :TEST (QUOTE STRING=)) (SERVER:MAIN)) :CURRENT-INDEX \
6)                                                                                                                                                                                                                 
16: (SB-C::%DO-FORMS-FROM-INFO #<FUNCTION (LAMBDA (SB-KERNEL:FORM &KEY :CURRENT-INDEX &ALLOW-OTHER-KEYS) :IN SB-INT:LOAD-AS-SOURCE) {10009E9A2B}> #<SB-C::SOURCE-INFO {10009E99F3}> SB-C::INPUT-ERROR-IN-LOAD)     
17: (SB-INT:LOAD-AS-SOURCE #<SB-SYS:FD-STREAM for "file /app/launch.lisp" {10009E8C33}> :VERBOSE NIL :PRINT NIL :CONTEXT "loading")                                                                                
18: ((FLET SB-FASL::THUNK :IN LOAD))                                                                                                                                                                               
19: (SB-FASL::CALL-WITH-LOAD-BINDINGS #<FUNCTION (FLET SB-FASL::THUNK :IN LOAD) {7FDED8F8F74B}> #<SB-SYS:FD-STREAM for "file /app/launch.lisp" {10009E8C33}>)                                                      
20: ((FLET SB-FASL::LOAD-STREAM :IN LOAD) #<SB-SYS:FD-STREAM for "file /app/launch.lisp" {10009E8C33}> NIL)                                                                                                        
21: (LOAD #<SB-SYS:FD-STREAM for "file /app/launch.lisp" {10009E8C33}> :VERBOSE NIL :PRINT NIL :IF-DOES-NOT-EXIST T :EXTERNAL-FORMAT :DEFAULT)                                                                     
22: ((FLET SB-IMPL::LOAD-SCRIPT :IN SB-IMPL::PROCESS-SCRIPT) #<SB-SYS:FD-STREAM for "file /app/launch.lisp" {10009E8C33}>)                                                                                         
23: ((FLET SB-UNIX::BODY :IN SB-IMPL::PROCESS-SCRIPT))                                                                                                                                                             
24: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-IMPL::PROCESS-SCRIPT))                                                                                                                                              
25: (SB-IMPL::PROCESS-SCRIPT "launch.lisp")                                                                                                                                                                        
26: (SB-IMPL::TOPLEVEL-INIT)                                                                                                                                                                                       
27: ((FLET SB-UNIX::BODY :IN SB-IMPL::START-LISP))                                                                                                                                                                 
28: ((FLET "WITHOUT-INTERRUPTS-BODY-1" :IN SB-IMPL::START-LISP))                                                                                                                                                   
29: (SB-IMPL::START-LISP)                                                                                                                                                                                          

Why the change?

SBCL is slightly more well supported than CCL. We used to use CCL for its Java support, but presently most of our plugins do not depend on Java. So we've made the decision to switch our default implementation to SBCL.

Migrating

In order to migrate, modify the Dockerfile to use --load instead of --script in the ENTRYPOINT. i.e. the ENTRYPOINT should look like:

ENTRYPOINT ["sbcl", "--load", "launch.lisp"]

Now rebuild the docker image:

docker-compose build screenshotbot

And run the docker image with an interactive terminal:

docker-compose run -T screenshotbot

This time, when the exception happens, it should enter a debugger. The debugger will give you some options to recover from the exception. Most likely the top "restart looks like this:

restarts (invokable by number or by possibly-abbreviated name):                                                                                                                                                    
  0: [INITIALIZE-STORE-RANDOM-STATE] Initialize the random state of the store.  Use                                                                                                                                
this to reinitialize the random state of the store when porting over a                                                                                                                                             
store from another compiler. When transactions of the application                                                                                                                                                  
depend on the random state, you must snapshot your store before                                                                                                                                                    
porting to the new compiler.                                                                                                                                                                                       

Press 0, and press enter.

If all goes well, everything should load from this point, and drop you to a console.

Exit from the console (either Ctrl+D, or (quit)), undo your changes to Dockerfile, rerun docker-compose build screenshotbot, and launch the docker image as you normally would. It should load correctly.