diff options
author | Daniel Colascione <dancol@dancol.org> | 2019-01-15 17:36:54 -0500 |
---|---|---|
committer | Daniel Colascione <dancol@dancol.org> | 2019-01-15 17:37:36 -0500 |
commit | d12e5d003d503025c1c9b0335d6518a6c3bdfae1 (patch) | |
tree | 41829446caca2d488e723843046c4f5b8931d8f8 /src/emacs.c | |
parent | 2a3bd6798e9670828f0402079fcc116d6d6b042d (diff) | |
download | emacs-d12e5d003d503025c1c9b0335d6518a6c3bdfae1.tar.gz |
Add portable dumper
Add a new portable dumper as an alternative to unexec. Use it by default.
* src/dmpstruct.awk: New file.
* src/doc.c (get_doc_string): use will_dump_p().
* src/editfns.c (styled_format): silence compiler warning
with UNINIT.
* src/emacs-module.c (syms_of_module): staticpro ltv_mark.
* src/emacs.c (gflags): new variable.
(init_cmdargs): unwrap
(string_starts_with_p, find_argument, dump_error_to_string)
(load_pdump): new functions.
(main): detect pdumper and --temacs invocation; actually load
portable dump when detected; set gflags as appropriate; changes to
init functions throughout to avoid passing explicit
'initialized' argument.
* src/eval.c (inhibit_lisp_code): remove unused variable.
(init_eval_once_for_pdumper): new function.
(init_eval_once): call it.
* src/filelock.c: CANNOT_DUMP -> will_dump_p()
* src/fingerprint-dummy.c: new file
* src/fingerprint.h: new file
* src/fns.c: CANNOT_DUMP -> will_dump_p(), etc.
(weak_hash_tables): remove
(hashfn_equal, hashfn_eql): un-staticify
(make_hash_table): set new 'next_weak' hash table field; drop
global weak_hash_tables logic.
(copy_hash_table): drop global weak_hash_tables logic.
(hash_table_rehash): new function.
(hash_lookup, hash_put, hash_remove_from_table, hash_clear):
rehash if needed.
(sweep_weak_table): un-staticify; explain logic; bool-ify.
(sweep_weak_hash_tables): remove function.
* src/font.c (syms_of_font): remember pdumper stuff.
* src/fontset.c (syms_of_fontset): remember pdumper stuff.
* src/frame.c (make_initial_frame): don't reset Vframe_list.
(init_frame_once_for_pdumper, init_frame_once): new functions.
(syms_of_frame): remove redundant staticpro.
* src/fringe.c (init_fringe_once_for_pdumper): new functin.
(init_fringe_once): call it.
* src/ftcrfont.c (syms_of_ftcrfont_for_pdumper): new function.
(syms_of_ftcrfont): call it.
* src/ftfont.c (syms_of_ftfont_for_pdumper): new function.
(syms_of_ftfont): call it.
* src/ftxont.c (syms_of_ftxfont_for_pdumper): new function.
(syms_of_ftxfont): call it.
* src/gmalloc.c: adjust for pdumper througout
(DUMPED): remove weird custom dumped indicator.
* src/gnutls.c (syms_of_gnutls): pdumper note for
gnutls_global_initialized.
* src/image.c (syms_of_image): add pdumper comment,
initializer note.
* src/insdel.c (prepare_to_modify_buffer_1): account
for buffer contents possibly being in dump image.
* src/keyboard.c (syms_of_keyboard_for_pdumper): new function.
(syms_of_keyboard): staticpro more; call pdumper syms function.
* src/lisp.h: add comments throughout
(gflags): declare.
(will_dump_p, will_bootstrap_p, will_dump_with_pdumper_p)
(dumped_with_pdumper_p, will_dump_with_unexec_p)
(dumped_with_unexec_p, definitely_will_not_unexec_p): new
functions.
(POWER_OF_2, ROUNDUP): move macros.
(PSEUDOVECTOR_TYPE, PSEUDOVECTOR_TYPEP): take vectorlike header
pointer instead of vector; constify.
(Lisp_Hash_Table): add comment about need to rehash on access; add
comment for next_weak.
(HASH_KEY, HASH_VALUE, HASH_HASH, HASH_TABLE_SIZE): const-ify.
(hash_table_rehash): declare.
(hash_rehash_needed_p, hash_rehash_if_needed): new functions.
(finalizers, doomed_finalizers): declare extern.
(SUBR_SECTION_ATTRIBUTE): new macro.
(staticvec, staticidx): un-static-ify.
(sweep_weak_hash_tables): remove declaration.
(sweep_weak_table): declare.
(hashfn_eql, hashfn_equal): declare.
(number_finalizers_run): new variable.
(Vdead): externify when ENABLE_CHECKING.
(gc_root_type): new enumeration.
(gc_root_visitor): new struct.
(visit_static_gc_roots): declare.
(vectorlike_nbytes): declare.
(vector_nbytes): define as trivial inline function wrapper for
vectorlike_nbytes.
(init_obarray_once): change signature.
(primary_thread): extern-ify.
(init_buffer): change signature.
(init_frame_once): declare.
* src/lread.c (readevalloop): adjust for new dumped predicates.
(init_obarray_once): new function.
(ndefsubr): new variable.
(defsubr): increment it.
(load_path_check): adjust for pdumper.
(load_path_default): use pdumper functions; adjust for
dump search.
* src/macfont.m (macfont_init_font_change_handler): avoid
shadowing global.
(syms_of_macfont_for_pdumper): new function.
(syms_of_macfont): call it.
* src/menu.c (syms_of_menu): staticpro more stuff.
* src/minibuf.c (Ftry_completion): rehash if needed.
(init_minibuf_once_for_pdumper): new function.
(init_minibuf_once): call it.
* src/nsfont.m (syms_of_nsfns): staticpro more.
* src/nsfont.m (syms_of_nsfont_for_pdumper): new function.
(syms_of_nsfont): call it.
* src/nsterm.m (syms_of_nsfont): remember pdumper stuff.
* src/pdumper.c: new file.
* src/pdumper.h: new file.
* src/process.c (init_process_emacs): use new pdumper functions
instead of CANNOT_DUMP.
* src/profiler.c (syms_of_profiler_for_pdumper): new function.
(syms_of_profiler_for_pdumper): call it.
* src/search.c (syms_of_search_for_pdumper): new function.
(syms_of_search_for_pdumper): call it.
* src/sheap.c (bss_sbrk_did_unexec): remove.
* src/sheap.h (bss_sbrk_did_unexec): remove.
* src/syntax.c (syms_of_syntax): don't redundantly staticpro
re_match_object.
* src/sysdep.c: use will_dump_with_unexec_p() instead of bss
hack thing.
* src/syssignals.h (init_sigsegv): declare.
* src/systime.h (init_timefns): remove bool from signature.
* src/textprop.c (syms_of_textprop): move staticpro.
* src/thread.c (main_thread_p): constify.
* src/thread.h (main_thread_p): constify.
* src/timefns.c (init_timefns): remove bool from signature.
(syms_of_timefns_for_pdumper): new function.
(syms_of_timefns): call it.
* src/w32.c: rearrange code.
* src/w32.h (w32_relocate): declare.
* src/w32fns.c (syms_of_w32fns): add pdumper note.
* src/w32font.c (syms_of_w32font_for_pdumper): new function.
(syms_of_w32font): call it.
* src/w32heap.c (using_dynamic_heap): new variable.
(init_heap): use it.
* src/w32menu.c (syms_of_w32menu): add pdumper note.
* src/w32proc.c
(ctrl_c_handler, mainCRTStartup, _start, open_input_file)
(rva_to_section, close_file_data): move here.
* src/w32uniscribe.c (syms_of_w32uniscribe_for_pdumper):
new function.
(syms_of_w32uniscribe): call it.
* src/window.c (init_window_once_for_pdumper): new function.
(init_window_once): call it; staticpro more stuff.
* src/xfont.c (syms_of_xfont_for_pdumper): new function.
(syms_of_xfont): call it.
* src/xftfont.c (syms_of_xftfont_for_pdumper): new function.
(syms_of_xftfont): call it.
* src/xmenu.c (syms_of_xmenu_for_pdumper): new function.
(syms_of_xmenu): call it.
* src/xselect.c (syms_of_xselect_for_pdumper): new function.
(syms_of_xselect): call it.
* src/xsettings.c (syms_of_xsettings): add more pdumper notes.
* src/term.c (syms_of_xterm): add pdumper note.
* src/dispnew.c (init_faces_initial): new function.
(init_display_interactive): rename from init_display; use
will_dump_p instead of !initialized. Initialize faces early for
pdumper if needed.
(init_display): new function.
(syms_of_display_for_pdumper): new function.
(syms_of_display): call it.
* src/dbusbind.c (syms_of_dbusbind): Add TODO for bus reset
on pdumper load.
* src/data.c (Fdefalias): Use will_dump_p
instead of Vpurify_flag.
(Fmake_variable_buffer_local): silence compiler warning with -Og
by making valcontents UNINIT.
(arith_driver): silence compiler warning with UNINIT.
* src/conf_post.h (ATTRIBUTE_SECTION): new macro.
* src/composite.c (composition_gstring_put_cache): rehash hash
table if needed.
* src/coding.c (init_coding_once, syms_of_coding): remember
pdumper stuff.
* src/charset.h (charset_table_size, charset_table_user): declare.
* src/charset.c (charset_table_used, charset_table_size): un-static.
(init_charset_oncem, syms_of_charset): remember pdumper stuff.
* src/category.c (category_table_version): remove obsolete
variable.
* src/callint.c (syms_of_callint): staticpro 'preserved_fns'
(init_callproc): use will_dump_p instead of !CANNOT_DUMP.
* src/bytecode.c (exec_byte_code): rehash table tables if needed
* src/buffer.c (alloc_buffer_text, free_buffer_text): account for
pdumper
(init_buffer_once): add TODO; remember stuff for pdumper.
(init_buffer): don't take initialized argument; adjust
for pdumper.
* src/atimer.c (init_atimer): initialize subr only if
!initialized.
* src/alloc.c: (vector_marked_p, set_vector_marked)
(vectorlike_marked_p, set_vectorlike_marked, cons_marked_p)
(set_cons_marked, string_marked_p, set_string_marked)
(symbol_marked_p, set_symbol_marked, interval_marked_p)
(set_interval_marked): new accessor routines. Use them
instead of raw GC access throughout.
(Vdead): make non-static when ENABLE_CHECKING.
(vectorlike_nbytes): rename of 'vector_nbytes'; take a vectorlike
header as input instead of a vector.
(number_finalizers_run): new internal C variable.
(mark_maybe_object): check for pdumper objects.
(valid_pointer_p): don't be gratuitously inefficient under rr(1).
(make_pure_c_string): add support for size_byte = -2 mode
indicating that string data points into Emacs image rodata.
(visit_vectorlike_root): visits GC roots embedded in
vectorlike objects.
(visit_buffer_root): visits GC roots embedded in
our totally-not-a-buffer buffer global objects.
(visit_static_gc_roots): visit GC roots in the Emacs data section.
(mark_object_root_visitor): root callback used for conventional GC
marking
(weak_hash_tables): new internal variable for tracking found weak
hash tables during GC.
(mark_and_sweep_weak_table_contents): new weak hash table marking.
(garbage_collect_1): use new GC root visitor machinery.
(mark_vectorlike): accept a vectorlike_header instead of a
Lisp_Vector.
(mark_frame, mark_window, mark_hash_table): new functions.
(mark_object): initialize 'm'; check for pdumper objects and use
new mark-bit accessors throughout. Remove some object-specific
marking code and move to helper functions above.
(survives_gc_p): check for pdumper objects.
(gc-sweep): clear pdumper mark bits.
(init_alloc_once_for_pdumper): new helper function for early init
called both during normal init and pdumper load.
(init_alloc_once): pdumper integration.
* src/Makefile.in: Rewrite dumping for pdumper; add pdumper.o;
invoke temacs with --temacs command line option; build dmpstruct.h
from dmpstruct.awk; stop relying on CANNOT_DUMP; clean up pdumper
intermediate files during build.
* nextstep/Makefile.in: build emacs.pdmp into NS packages
* lisp/startup.el: account for new '--temacs' and '--dump-file'
command line option.
* lisp/loadup.el: rewrite early init to account for pdumper; use
injected 'dump-mode' variable (set via the new '--temacs' option)
instead of parsing command line.
* lisp/cus-start.el: Check 'dump-mode' instead of 'purify-flag',
since the new 'dump-mode'
* lib-src/make-fingerprint.c: new program
* lib-src/Makefile.in: built make-fingerprint utility program
* configure.ac: Add --with-pdumper toggle to control pdumper
support; add --with-unexec toggle to control unexec support.
Add --with-dumping option to control which dumping strategy we use
by default. Adjust for pdumper throughout. Check for
posix_madvise.
* Makefile.in: Add @DUMPING@ substitution; add pdumper mode.
* .gitignore: Add make-fingerprint, temacs.in, fingerprint.c,
dmpstruct.h, and pdumper dump files.
Diffstat (limited to 'src/emacs.c')
-rw-r--r-- | src/emacs.c | 304 |
1 files changed, 252 insertions, 52 deletions
diff --git a/src/emacs.c b/src/emacs.c index 221b074afc9..9c88b6e3f17 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -118,6 +118,9 @@ extern char etext; #include <sys/resource.h> #endif +#include "pdumper.h" +#include "epaths.h" + static const char emacs_version[] = PACKAGE_VERSION; static const char emacs_copyright[] = COPYRIGHT; static const char emacs_bugreport[] = PACKAGE_BUGREPORT; @@ -130,19 +133,9 @@ Lisp_Object empty_unibyte_string, empty_multibyte_string; Lisp_Object Vlibrary_cache; #endif -/* Set after Emacs has started up the first time. - Prevents reinitialization of the Lisp world and keymaps - on subsequent starts. */ +struct gflags gflags; bool initialized; -#ifndef CANNOT_DUMP -/* Set to true if this instance of Emacs might dump. */ -# ifndef DOUG_LEA_MALLOC -static -# endif -bool might_dump; -#endif - /* If true, Emacs should not attempt to use a window-specific code, but instead should use the virtual terminal under which it was started. */ bool inhibit_window_system; @@ -519,8 +512,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) etc_exists = Ffile_exists_p (tem); if (!NILP (etc_exists)) { - Vinstallation_directory - = Ffile_name_as_directory (dir); + Vinstallation_directory = Ffile_name_as_directory (dir); break; } } @@ -545,8 +537,7 @@ init_cmdargs (int argc, char **argv, int skip_args, char const *original_pwd) if (!NILP (etc_exists)) { tem = Fexpand_file_name (build_string (".."), dir); - Vinstallation_directory - = Ffile_name_as_directory (tem); + Vinstallation_directory = Ffile_name_as_directory (tem); break; } } @@ -659,6 +650,43 @@ argmatch (char **argv, int argc, const char *sstr, const char *lstr, } } +static bool +string_starts_with_p (const char* string, const char* prefix) +{ + return strncmp (string, prefix, strlen (prefix)) == 0; +} + +/* Return the value of GNU-style long argument ARGUMENT if given on + command line. ARGUMENT must begin with "-". If ARGUMENT is not + given, return NULL. */ +static char * +find_argument (const char *argument, int argc, char **argv) +{ + char *found = NULL; + int i; + + eassert (argument[0] == '-'); + + for (i = 1; i < argc; ++i) + if (string_starts_with_p (argv[i], argument) && + ((argv[i] + strlen (argument))[0] == '=' || + (argv[i] + strlen (argument))[0] == '\0')) + { + int j = i; + found = argv[j++] + strlen (argument); + if (*found == '=') + ++found; + else if (i < argc) + found = argv[j++]; + else + fatal ("no argument given for %s", argument); + break; + } + else if (strcmp (argv[i], "--") == 0) + break; + return found; +} + /* Close standard output and standard error, reporting any write errors as best we can. This is intended for use with atexit. */ static void @@ -677,6 +705,114 @@ close_output_streams (void) _exit (EXIT_FAILURE); } +#ifdef HAVE_PDUMPER + +static const char * +dump_error_to_string (enum pdumper_load_result result) +{ + switch (result) + { + case PDUMPER_LOAD_SUCCESS: + return "success"; + case PDUMPER_LOAD_OOM: + return "out of memory"; + case PDUMPER_NOT_LOADED: + return "not loaded"; + case PDUMPER_LOAD_FILE_NOT_FOUND: + return "could not open file"; + case PDUMPER_LOAD_BAD_FILE_TYPE: + return "not a dump file"; + case PDUMPER_LOAD_FAILED_DUMP: + return "dump file is result of failed dump attempt"; + case PDUMPER_LOAD_VERSION_MISMATCH: + return "not built for this Emacs executable"; + default: + return "generic error"; + } +} + +#define PDUMP_FILE_ARG "--dump-file" + +static enum pdumper_load_result +load_pdump (int argc, char **argv) +{ + const char *const suffix = ".pdmp"; + const char *const argv0_base = "emacs"; + enum pdumper_load_result result; +#ifdef WINDOWSNT + size_t argv0_len; +#endif + + /* TODO: maybe more thoroughly scrub process environment in order to + make this use case (loading a pdumper image in an unexeced emacs) + possible? Right now, we assume that things we don't touch are + zero-initialized, and in an unexeced Emacs, this assumption + doesn't hold. */ + if (initialized) + fatal ("cannot load pdumper image in unexeced Emacs"); + + /* Look for an explicitly-specified dump file. */ + const char *path_exec = PATH_EXEC; + char *dump_file = find_argument (PDUMP_FILE_ARG, argc, argv); + + result = PDUMPER_NOT_LOADED; + if (dump_file) + result = pdumper_load (dump_file); + + if (dump_file && result != PDUMPER_LOAD_SUCCESS) + fatal ("could not load dump file \"%s\": %s", + dump_file, dump_error_to_string (result)); + + if (result == PDUMPER_LOAD_SUCCESS) + goto out; + + /* Look for a dump file in the same directory as the executable; it + should have the same basename. */ + + dump_file = alloca (strlen (argv[0]) + strlen (suffix) + 1); +#ifdef WINDOWSNT + /* Remove the .exe extension if present. */ + argv0_len = strlen (argv[0]); + if (argv0_len >= 4 && c_strcasecmp (argv[0] + argv0_len - 4, ".exe") == 0) + sprintf (dump_file, "%.*s%s", argv0_len - 4, argv[0], suffix); + else +#endif + sprintf (dump_file, "%s%s", argv[0], suffix); + + result = pdumper_load (dump_file); + if (result == PDUMPER_LOAD_SUCCESS) + goto out; + + if (result != PDUMPER_LOAD_FILE_NOT_FOUND) + fatal ("could not load dump file \"%s\": %s", + dump_file, dump_error_to_string (result)); + + /* Finally, look for "emacs.pdmp" in PATH_EXEC. We hardcode + "emacs" in "emacs.pdmp" so that the Emacs binary still works + if the user copies and renames it. + + FIXME: this doesn't work with emacs-XX.YY.ZZ.pdmp versioned files. */ +#ifdef WINDOWSNT + /* On MS-Windows, PATH_EXEC normally starts with a literal + "%emacs_dir%", so it will never work without some tweaking. */ + path_exec = w32_relocate (path_exec); +#endif + dump_file = alloca (strlen (path_exec) + + 1 + + strlen (argv0_base) + + strlen (suffix) + + 1); + sprintf (dump_file, "%s%c%s%s", + path_exec, DIRECTORY_SEP, argv0_base, suffix); + result = pdumper_load (dump_file); + if (result != PDUMPER_LOAD_SUCCESS) + dump_file = NULL; + + out: + return result; +} +#endif /* HAVE_PDUMPER */ + /* ARGSUSED */ int main (int argc, char **argv) @@ -686,7 +822,6 @@ main (int argc, char **argv) void *stack_bottom_variable; bool do_initial_setlocale; - bool dumping; int skip_args = 0; bool no_loadup = false; char *junk = 0; @@ -702,25 +837,62 @@ main (int argc, char **argv) /* Record (approximately) where the stack begins. */ stack_bottom = (char *) &stack_bottom_variable; -#ifndef CANNOT_DUMP - dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0 - || strcmp (argv[argc - 1], "bootstrap") == 0); -#else - dumping = false; + const char *dump_mode = NULL; + const char *temacs = find_argument ("--temacs", argc, argv); +#ifdef HAVE_PDUMPER + bool attempt_load_pdump = false; #endif - argc = maybe_disable_address_randomization (dumping, argc, argv); - + /* Look for this argument first, before any heap allocation, so we + can set heap flags properly if we're going to unexec. */ + if (!initialized && temacs) + { #ifndef CANNOT_DUMP - might_dump = !initialized; - -# ifdef GNU_LINUX - if (!initialized) + if (strcmp (temacs, "dump") == 0 || + strcmp (temacs, "bootstrap") == 0) + gflags.will_dump_with_unexec_ = true; +#endif +#ifdef HAVE_PDUMPER + if (strcmp (temacs, "pdump") == 0 || + strcmp (temacs, "pbootstrap") == 0) + gflags.will_dump_with_pdumper_ = true; +#endif +#if defined (HAVE_PDUMPER) || !defined (CANNOT_DUMP) + if (strcmp (temacs, "bootstrap") == 0 || + strcmp (temacs, "pbootstrap") == 0) + gflags.will_bootstrap_ = true; + gflags.will_dump_ = + will_dump_with_pdumper_p () || + will_dump_with_unexec_p (); + if (will_dump_p ()) + dump_mode = temacs; +#endif + if (!dump_mode) + fatal ("Invalid temacs mode '%s'", temacs); + } + else if (temacs) { - char *heap_start = my_heap_start (); - heap_bss_diff = heap_start - max (my_endbss, my_endbss_static); + fatal ("--temacs not supported for unexeced emacs"); } -# endif + else if (initialized) + { +#ifdef HAVE_PDUMPER + if (find_argument (PDUMP_FILE_ARG, argc, argv)) + fatal ("%s not supported in unexeced emacs", PDUMP_FILE_ARG); +#endif + } + else + { + eassert (!initialized); + eassert (!temacs); +#ifdef PDUMP_FILE_ARG + attempt_load_pdump = true; +#endif + } + +#ifndef CANNOT_DUMP + if (!will_dump_with_unexec_p ()) + gflags.will_not_unexec_ = true; #endif #if defined WINDOWSNT || defined HAVE_NTGUI @@ -742,6 +914,22 @@ main (int argc, char **argv) w32_init_main_thread (); #endif +#ifdef HAVE_PDUMPER + if (attempt_load_pdump) + load_pdump (argc, argv); +#endif + + argc = maybe_disable_address_randomization ( + will_dump_with_unexec_p (), argc, argv); + +#if defined (GNU_LINUX) && !defined (CANNOT_DUMP) + if (!initialized) + { + char *heap_start = my_heap_start (); + heap_bss_diff = heap_start - max (my_endbss, my_endbss_static); + } +#endif + #ifdef RUN_TIME_REMAP if (initialized) run_time_remap (argv[0]); @@ -850,10 +1038,7 @@ main (int argc, char **argv) frames. */ int extra = (30 * 1000) * 50; - bool try_to_grow_stack = true; -#ifndef CANNOT_DUMP - try_to_grow_stack = !noninteractive || initialized; -#endif + bool try_to_grow_stack = !noninteractive || initialized; if (try_to_grow_stack) { @@ -1184,17 +1369,15 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #if defined HAVE_PTHREAD && !defined SYSTEM_MALLOC \ && !defined DOUG_LEA_MALLOC && !defined HYBRID_MALLOC -# ifndef CANNOT_DUMP /* Do not make gmalloc thread-safe when creating bootstrap-emacs, as that causes an infinite recursive loop with FreeBSD. See Bug#14569. The part of this bug involving Cygwin is no longer relevant, now that Cygwin defines HYBRID_MALLOC. */ - if (!noninteractive || initialized) -# endif + if (!noninteractive || !will_dump_p ()) malloc_enable_thread (); #endif - init_signals (dumping); + init_signals (); noninteractive1 = noninteractive; @@ -1204,7 +1387,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem { init_alloc_once (); init_threads_once (); - init_obarray (); + init_obarray_once (); init_eval_once (); init_charset_once (); init_coding_once (); @@ -1242,7 +1425,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem /* Before init_window_once, because it sets up the Vcoding_system_hash_table. */ syms_of_coding (); /* This should be after syms_of_fileio. */ - + init_frame_once (); /* Before init_window_once. */ init_window_once (); /* Init the window system. */ #ifdef HAVE_WINDOW_SYSTEM init_fringe_once (); /* Swap bitmaps if necessary. */ @@ -1282,7 +1465,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem bool module_assertions = argmatch (argv, argc, "-module-assertions", "--module-assertions", 15, NULL, &skip_args); - if (dumping && module_assertions) + if (will_dump_p () && module_assertions) { fputs ("Module assertions are not supported during dumping\n", stderr); exit (1); @@ -1419,7 +1602,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem /* egetenv is a pretty low-level facility, which may get called in many circumstances; it seems flimsy to put off initializing it until calling init_callproc. Do not do it when dumping. */ - if (! dumping) + if (!will_dump_p ()) set_initial_environment (); #ifdef WINDOWSNT @@ -1433,7 +1616,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem variables from the parent process without modifications from Emacs. */ init_environment (argv); - init_ntproc (dumping); /* must precede init_editfns. */ + init_ntproc (will_dump_p ()); /* must precede init_editfns. */ #endif /* AIX crashes are reported in system versions 3.2.3 and 3.2.4 @@ -1445,7 +1628,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem #endif /* Init buffer storage and default directory of main buffer. */ - init_buffer (initialized); + init_buffer (); init_callproc_1 (); /* Must precede init_cmdargs and init_sys_modes. */ @@ -1620,6 +1803,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem syms_of_threads (); syms_of_profiler (); + syms_of_pdumper (); #ifdef HAVE_JSON syms_of_json (); @@ -1650,7 +1834,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_charset (); /* This calls putenv and so must precede init_process_emacs. */ - init_timefns (dumping); + init_timefns (); /* This sets Voperating_system_release, which init_process_emacs uses. */ init_editfns (); @@ -1669,10 +1853,9 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_process_emacs (sockfd); init_keyboard (); /* This too must precede init_sys_modes. */ - if (!noninteractive) - init_display (); /* Determine terminal type. Calls init_sys_modes. */ + init_display (); /* Determine terminal type. Calls init_sys_modes. */ #if HAVE_W32NOTIFY - else + if (noninteractive) init_crit (); /* w32notify.c needs this in batch mode. */ #endif /* HAVE_W32NOTIFY */ init_xdisp (); @@ -1716,7 +1899,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem moncontrol (0); #endif - initialized = 1; + initialized = true; + + if (dump_mode) + Vdump_mode = build_string (dump_mode); /* Enter editor command loop. This never returns. */ Frecursive_edit (); @@ -2166,8 +2352,11 @@ You must run Emacs in batch mode in order to dump it. */) if (! noninteractive) error ("Dumping Emacs works only in batch mode"); - if (!might_dump) - error ("Emacs can be dumped only once"); + if (dumped_with_unexec_p ()) + error ("Emacs can be dumped using unexec only once"); + + if (definitely_will_not_unexec_p ()) + error ("This Emacs instance was not started in temacs mode"); #if defined GNU_LINUX && !defined CANNOT_DUMP @@ -2231,12 +2420,19 @@ You must run Emacs in batch mode in order to dump it. */) #endif /* not WINDOWSNT */ #endif /* not SYSTEM_MALLOC and not HYBRID_MALLOC */ + struct gflags old_gflags = gflags; + gflags.will_dump_ = false; + gflags.will_dump_with_unexec_ = false; + gflags.dumped_with_unexec_ = true; + alloc_unexec_pre (); unexec (SSDATA (filename), !NILP (symfile) ? SSDATA (symfile) : 0); alloc_unexec_post (); + gflags = old_gflags; + #ifdef WINDOWSNT Vlibrary_cache = Qnil; #endif @@ -2250,6 +2446,7 @@ You must run Emacs in batch mode in order to dump it. */) } #endif /* not CANNOT_DUMP */ + #if HAVE_SETLOCALE /* Recover from setlocale (LC_ALL, ""). */ @@ -2585,7 +2782,7 @@ Don't rely on it for testing whether a feature you want to use is available. */ Vsystem_configuration_features = build_string (EMACS_CONFIG_FEATURES); DEFVAR_BOOL ("noninteractive", noninteractive1, - doc: /* Non-nil means Emacs is running without interactive terminal. */); + doc: /* Non-nil means Emacs is running without interactive terminal. */); DEFVAR_LISP ("kill-emacs-hook", Vkill_emacs_hook, doc: /* Hook run when `kill-emacs' is called. @@ -2670,6 +2867,9 @@ component .BUILD is present. This is now stored separately in doc: /* Address of mailing list for GNU Emacs bugs. */); Vreport_emacs_bug_address = build_string (emacs_bugreport); + DEFVAR_LISP ("dump-mode", Vdump_mode, + doc: /* Non-nil when Emacs is dumping itself. */); + DEFVAR_LISP ("dynamic-library-alist", Vdynamic_library_alist, doc: /* Alist of dynamic libraries vs external files implementing them. Each element is a list (LIBRARY FILE...), where the car is a symbol |