From d12e5d003d503025c1c9b0335d6518a6c3bdfae1 Mon Sep 17 00:00:00 2001 From: Daniel Colascione Date: Tue, 15 Jan 2019 17:36:54 -0500 Subject: 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. --- src/emacs.c | 304 +++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 252 insertions(+), 52 deletions(-) (limited to 'src/emacs.c') 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 #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 -- cgit v1.2.1