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