1;;;; Dump the current Lisp image into a core file. Also contains 2;;;; various high-level initialization stuff: loading init files and 3;;;; parsing environment variables. 4;;;; 5;;;; (All the real work is done by C.) 6 7;;;; This software is part of the SBCL system. See the README file for 8;;;; more information. 9;;;; 10;;;; This software is derived from the CMU CL system, which was 11;;;; written at Carnegie Mellon University and released into the 12;;;; public domain. The software is in the public domain and is 13;;;; provided with absolutely no warranty. See the COPYING and CREDITS 14;;;; files for more information. 15 16(in-package "SB!IMPL") 17 18;;;; SAVE-LISP-AND-DIE itself 19 20(define-alien-routine "save" (boolean) 21 (file c-string) 22 (initial-fun (unsigned #.sb!vm:n-word-bits)) 23 (prepend-runtime int) 24 (save-runtime-options int) 25 (compressed int) 26 (compression-level int) 27 (application-type int)) 28 29#!+gencgc 30(define-alien-routine "gc_and_save" void 31 (file c-string) 32 (prepend-runtime int) 33 (save-runtime-options int) 34 (compressed int) 35 (compression-level int) 36 (application-type int)) 37 38#!+gencgc 39(defvar sb!vm::*restart-lisp-function*) 40 41(define-condition save-condition (reference-condition) 42 () 43 (:default-initargs 44 :references (list '(:sbcl :node "Saving a Core Image")))) 45 46(define-condition save-error (error save-condition) 47 () 48 (:report "Could not save core.")) 49 50(define-condition save-with-multiple-threads-error (save-error) 51 ((interactive-thread :initarg :interactive-threads 52 :reader save-with-multiple-threads-error-interactive-threads) 53 (other-threads :initarg :other-threads 54 :reader save-with-multiple-threads-error-other-threads)) 55 (:report (lambda (condition stream) 56 (let ((interactive (save-with-multiple-threads-error-interactive-threads condition)) 57 (other (save-with-multiple-threads-error-other-threads condition))) 58 (format stream "~@<Cannot save core with multiple threads running.~ 59 ~@:_~@:_Interactive thread~P (of current session):~ 60 ~@:_~2@T~<~{~A~^, ~}~:>~ 61 ~@:_~@:_Other thread~P:~ 62 ~@:_~2@T~<~{~A~^, ~}~:>~@:>" 63 (length interactive) (list interactive) 64 (length other) (list other)))))) 65 66(defun save-lisp-and-die (core-file-name &key 67 (toplevel #'toplevel-init) 68 (executable nil) 69 (save-runtime-options nil) 70 (purify t) 71 (root-structures ()) 72 (environment-name "auxiliary") 73 (compression nil) 74 #!+win32 75 (application-type :console)) 76 #!+sb-doc 77 "Save a \"core image\", i.e. enough information to restart a Lisp 78process later in the same state, in the file of the specified name. 79Only global state is preserved: the stack is unwound in the process. 80 81The following &KEY arguments are defined: 82 83 :TOPLEVEL 84 The function to run when the created core file is resumed. The 85 default function handles command line toplevel option processing 86 and runs the top level read-eval-print loop. This function returning 87 is equivalent to (SB-EXT:EXIT :CODE 0) being called. 88 89 TOPLEVEL functions should always provide an ABORT restart: otherwise 90 code they call will run without one. 91 92 :EXECUTABLE 93 If true, arrange to combine the SBCL runtime and the core image 94 to create a standalone executable. If false (the default), the 95 core image will not be executable on its own. Executable images 96 always behave as if they were passed the --noinform runtime option. 97 98 :SAVE-RUNTIME-OPTIONS 99 If true, values of runtime options --dynamic-space-size and 100 --control-stack-size that were used to start SBCL are stored in 101 the standalone executable, and restored when the executable is 102 run. This also inhibits normal runtime option processing, causing 103 all command line arguments to be passed to the toplevel. 104 Meaningless if :EXECUTABLE is NIL. 105 106 :PURIFY 107 If true (the default on cheneygc), do a purifying GC which moves all 108 dynamically allocated objects into static space. This takes 109 somewhat longer than the normal GC which is otherwise done, but 110 it's only done once, and subsequent GC's will be done less often 111 and will take less time in the resulting core file. See the PURIFY 112 function. This parameter has no effect on platforms using the 113 generational garbage collector. 114 115 :ROOT-STRUCTURES 116 This should be a list of the main entry points in any newly loaded 117 systems. This need not be supplied, but locality and/or GC performance 118 may be better if they are. This has two different but related meanings: 119 If :PURIFY is true - and only for cheneygc - the root structures 120 are those which anchor the set of objects moved into static space. 121 On gencgc - and only on platforms supporting immobile code - these are 122 the functions and/or function-names which commence a depth-first scan 123 of code when reordering based on the statically observable call chain. 124 The complete set of reachable objects is not affected per se. 125 This argument is meaningless if neither enabling precondition holds. 126 127 :ENVIRONMENT-NAME 128 This has no purpose; it is accepted only for legacy compatibility. 129 130 :COMPRESSION 131 This is only meaningful if the runtime was built with the :SB-CORE-COMPRESSION 132 feature enabled. If NIL (the default), saves to uncompressed core files. If 133 :SB-CORE-COMPRESSION was enabled at build-time, the argument may also be 134 an integer from -1 to 9, corresponding to zlib compression levels, or T 135 (which is equivalent to the default compression level, -1). 136 137 :APPLICATION-TYPE 138 Present only on Windows and is meaningful only with :EXECUTABLE T. 139 Specifies the subsystem of the executable, :CONSOLE or :GUI. 140 The notable difference is that :GUI doesn't automatically create a console 141 window. The default is :CONSOLE. 142 143The save/load process changes the values of some global variables: 144 145 *STANDARD-OUTPUT*, *DEBUG-IO*, etc. 146 Everything related to open streams is necessarily changed, since 147 the OS won't let us preserve a stream across save and load. 148 149 *DEFAULT-PATHNAME-DEFAULTS* 150 This is reinitialized to reflect the working directory where the 151 saved core is loaded. 152 153SAVE-LISP-AND-DIE interacts with SB-ALIEN:LOAD-SHARED-OBJECT: see its 154documentation for details. 155 156On threaded platforms only a single thread may remain running after 157SB-EXT:*SAVE-HOOKS* have run. Applications using multiple threads can 158be SAVE-LISP-AND-DIE friendly by registering a save-hook that quits 159any additional threads, and an init-hook that restarts them. 160 161This implementation is not as polished and painless as you might like: 162 * It corrupts the current Lisp image enough that the current process 163 needs to be killed afterwards. This can be worked around by forking 164 another process that saves the core. 165 * There is absolutely no binary compatibility of core images between 166 different runtime support programs. Even runtimes built from the same 167 sources at different times are treated as incompatible for this 168 purpose. 169This isn't because we like it this way, but just because there don't 170seem to be good quick fixes for either limitation and no one has been 171sufficiently motivated to do lengthy fixes." 172 (declare (ignore environment-name)) 173 #!+gencgc 174 (declare (ignore purify) (ignorable root-structures)) 175 #!+sb-core-compression 176 (check-type compression (or boolean (integer -1 9))) 177 #!-sb-core-compression 178 (when compression 179 (error "Unable to save compressed core: this runtime was not built with zlib support")) 180 (when *dribble-stream* 181 (restart-case (error "Dribbling to ~s is enabled." (pathname *dribble-stream*)) 182 (continue () 183 :report "Stop dribbling and save the core." 184 (dribble)) 185 (abort () 186 :report "Abort saving the core." 187 (return-from save-lisp-and-die)))) 188 (when (eql t compression) 189 (setf compression -1)) 190 (labels ((restart-lisp () 191 (handling-end-of-the-world 192 (reinit) 193 #!+hpux (%primitive sb!vm::setup-return-from-lisp-stub) 194 (funcall toplevel))) 195 (foreign-bool (value) 196 (if value 1 0))) 197 (let ((name (native-namestring (physicalize-pathname core-file-name) 198 :as-file t))) 199 (tune-image-for-dump) 200 (deinit) 201 ;; FIXME: Would it be possible to unmix the PURIFY logic from this 202 ;; function, and just do a GC :FULL T here? (Then if the user wanted 203 ;; a PURIFYed image, he'd just run PURIFY immediately before calling 204 ;; SAVE-LISP-AND-DIE.) 205 #!+gencgc 206 (progn 207 ;; Scan roots as close as possible to GC-AND-SAVE, in case anything 208 ;; prior causes compilation to occur into immobile space. 209 ;; Failing to see all immobile code would miss some relocs. 210 #!+immobile-code (sb!kernel::choose-code-component-order root-structures) 211 ;; Save the restart function into a static symbol, to allow GC-AND-SAVE 212 ;; access to it even after the GC has moved it. 213 (setf sb!vm::*restart-lisp-function* #'restart-lisp) 214 ;; Do a destructive non-conservative GC, and then save a core. 215 ;; A normal GC will leave huge amounts of storage unreclaimed 216 ;; (over 50% on x86). This needs to be done by a single function 217 ;; since the GC will invalidate the stack. 218 (gc-and-save name 219 (foreign-bool executable) 220 (foreign-bool save-runtime-options) 221 (foreign-bool compression) 222 (or compression 0) 223 #!+win32 (ecase application-type (:console 0) (:gui 1)) 224 #!-win32 0)) 225 #!-gencgc 226 (progn 227 (if purify (purify :root-structures root-structures) (gc)) 228 (without-gcing 229 (save name 230 (get-lisp-obj-address #'restart-lisp) 231 (foreign-bool executable) 232 (foreign-bool save-runtime-options) 233 (foreign-bool compression) 234 (or compression 0) 235 #!+win32 (ecase application-type (:console 0) (:gui 1)) 236 #!-win32 0))))) 237 238 ;; Something went very wrong -- reinitialize to have a prayer 239 ;; of being able to report the error. 240 (reinit) 241 (error 'save-error)) 242 243(defun tune-image-for-dump () 244 #!+sb-fasteval (sb!interpreter::flush-everything) 245 (tune-hashtable-sizes-of-all-packages)) 246 247(defun deinit () 248 (call-hooks "save" *save-hooks*) 249 #!+sb-wtimer 250 (itimer-emulation-deinit) 251 (let ((threads (sb!thread:list-all-threads))) 252 (unless (= 1 (length threads)) 253 (let* ((interactive (sb!thread::interactive-threads)) 254 (other (set-difference threads interactive))) 255 (error 'save-with-multiple-threads-error 256 :interactive-threads interactive 257 :other-threads other)))) 258 (float-deinit) 259 (profile-deinit) 260 (foreign-deinit) 261 (stream-deinit) 262 (deinit-finalizers) 263 (drop-all-hash-caches) 264 (os-deinit) 265 (setf * nil ** nil *** nil 266 - nil + nil ++ nil +++ nil 267 /// nil // nil / nil)) 268