Subject: bug#42832: 28.0.50; "Bus error" when compiling Emacs now on Debian bullseye

From: Pip Cet <[email-masked]>
Date: Fri, 14 Aug 2020 15:01:44 +0000

On Fri, Aug 14, 2020 at 2:24 PM Pip Cet <[email-masked]> wrote:
> If no, any ideas on how to fix it? The obvious fix would be to always
> mark all pdumped objects, but that has a performance cost. Less
> obvious would be clearing the memory in the pdumper image that belongs
> to an object that's being "freed", or keeping track of which pdumper
> objects are still valid after GC...

I've gone with the last idea. This patch should fix things, though
given how difficult the bug is to trigger reliably it might also
merely appear to fix it...
From e5e7445625c4727067b6e056bf736a2c8db37602 Mon Sep 17 00:00:00 2001
From: Pip Cet <[email-masked]>
Date: Fri, 14 Aug 2020 14:56:19 +0000
Subject: [PATCH] Try to avoid marking zombie pdumper objects.

---
 src/pdumper.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/pdumper.c b/src/pdumper.c
index bc41afc7c5..812eb18de9 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -4871,6 +4871,8 @@ dump_bitset_clear (struct dump_bitset *bitset)
   struct dump_header header;
   /* Mark bits for objects in the dump; used during GC.  */
   struct dump_bitset mark_bits;
+  /* Mark bits for objects in the dump; used during GC.  */
+  struct dump_bitset last_mark_bits;
   /* Time taken to load the dump.  */
   double load_time;
   /* Dump file name.  */
@@ -4995,6 +4997,9 @@ pdumper_find_object_type_impl (const void *obj)
     return PDUMPER_NO_OBJECT;
   const struct dump_reloc *reloc =
     dump_find_relocation (&dump_private.header.object_starts, offset);
+  ptrdiff_t bitno = offset / DUMP_ALIGNMENT;
+  if (!dump_bitset_bit_set_p (&dump_private.last_mark_bits, bitno))
+    return PDUMPER_NO_OBJECT;
   return (reloc != NULL && dump_reloc_get_offset (*reloc) == offset)
     ? reloc->type
     : PDUMPER_NO_OBJECT;
@@ -5021,12 +5026,16 @@ pdumper_set_marked_impl (const void *obj)
   eassert (offset < dump_private.header.cold_start);
   eassert (offset < dump_private.header.discardable_start);
   ptrdiff_t bitno = offset / DUMP_ALIGNMENT;
+  eassert (dump_bitset_bit_set_p (&dump_private.last_mark_bits, bitno));
   dump_bitset_set_bit (&dump_private.mark_bits, bitno);
 }
 
 void
 pdumper_clear_marks_impl (void)
 {
+  memcpy (dump_private.last_mark_bits.bits, dump_private.mark_bits.bits,
+	  sizeof (dump_private.last_mark_bits.bits[0])
+	  * dump_private.mark_bits.number_words);
   dump_bitset_clear (&dump_private.mark_bits);
 }
 
@@ -5244,6 +5253,7 @@ pdumper_load (const char *dump_filename)
   dump_off adj_discardable_start;
 
   struct dump_bitset mark_bits;
+  struct dump_bitset last_mark_bits;
   size_t mark_bits_needed;
 
   struct dump_header header_buf = { 0 };
@@ -5360,12 +5370,18 @@ pdumper_load (const char *dump_filename)
   if (!dump_bitset_init (&mark_bits, mark_bits_needed))
     goto out;
 
+  if (!dump_bitset_init (&last_mark_bits, mark_bits_needed))
+    goto out;
+
+  memset (last_mark_bits.bits, 0xff, sizeof (last_mark_bits.bits[0] * last_mark_bits.number_words));
+
   /* Point of no return.  */
   err = PDUMPER_LOAD_SUCCESS;
   dump_base = (uintptr_t) sections[DS_HOT].mapping;
   gflags.dumped_with_pdumper_ = true;
   dump_private.header = *header;
   dump_private.mark_bits = mark_bits;
+  dump_private.last_mark_bits = last_mark_bits;
   dump_public.start = dump_base;
   dump_public.end = dump_public.start + dump_size;
 
-- 
2.28.0