Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Allow dlsym to call free() on memory that is allocated before mmalloc init
authorMartin Quinson <martin.quinson@ens-rennes.fr>
Thu, 28 Jul 2022 01:06:38 +0000 (03:06 +0200)
committerMartin Quinson <martin.quinson@ens-rennes.fr>
Thu, 28 Jul 2022 01:49:23 +0000 (03:49 +0200)
dlsym obviously uses malloc, but we use dlsym while initializing
mmalloc, so we have a static buffer somewhere to give the required
memory to dlsym while mmalloc is not ready to serve. That's old.

Now, since the recent change in mmalloc, dlsym seems to not only
malloc some memory, but it also frees some of the obtained memory.
This commit detects when this happens and react gracefully (by
ignoring the free on that memory) instead of verbosely dying.

src/xbt/mmalloc/mfree.c
src/xbt/mmalloc/mm_legacy.c
src/xbt/mmalloc/mmprivate.h

index 4863878..652b381 100644 (file)
@@ -29,6 +29,11 @@ void mfree(struct mdesc *mdp, void *ptr)
   size_t block = BLOCK(ptr);
 
   if ((char *) ptr < (char *) mdp->heapbase || block > mdp->heapsize) {
+    if ((char*)ptr <= (char*)mmalloc_preinit_buffer + mmalloc_preinit_buffer_size &&
+        (char*)ptr >= (char*)mmalloc_preinit_buffer)
+      /* This points to the static buffer for fake mallocs done by dlsym before mmalloc initialization, ignore it */
+      return;
+
     fprintf(stderr,"Ouch, this pointer is not mine, I refuse to free it. Give me valid pointers, or give me death!!\n");
     abort();
   }
index 84a7eb4..7b946b5 100644 (file)
@@ -44,13 +44,9 @@ xbt_mheap_t mmalloc_get_current_heap(void)
  * This is used before we have found the real malloc implementation with dlsym.
  */
 
-#ifdef __FreeBSD__ /* FreeBSD require more memory, other might */
-# define BUFFER_SIZE 256
-#else /* Valid on: Linux */
-# define BUFFER_SIZE 32
-#endif
 static size_t fake_alloc_index;
-static uint64_t buffer[BUFFER_SIZE];
+static uint64_t buffer[mmalloc_preinit_buffer_size];
+uint64_t* mmalloc_preinit_buffer = buffer;
 
 /* Fake implementations, they are used to fool dlsym:
  * dlsym used calloc and falls back to some other mechanism
@@ -58,13 +54,18 @@ static uint64_t buffer[BUFFER_SIZE];
  */
 static void* mm_fake_malloc(size_t n)
 {
+  mmalloc_preinit_buffer = buffer;
+
   // How many uint64_t do w need?
   size_t count = n / sizeof(uint64_t);
   if (n % sizeof(uint64_t))
     count++;
   // Check that we have enough available memory:
-  if (fake_alloc_index + count >= BUFFER_SIZE)
+  if (fake_alloc_index + count >= mmalloc_preinit_buffer_size) {
+    puts("mmalloc is not initialized yet, but the static buffer used as malloc replacement is already exhausted. "
+         "Please increase `mmalloc_preinit_buffer_size` in mm_legacy.c\n");
     exit(127);
+  }
   // Allocate it:
   uint64_t* res = buffer + fake_alloc_index;
   fake_alloc_index += count;
index 2756de4..cddfd15 100644 (file)
@@ -274,6 +274,16 @@ XBT_PRIVATE int malloc_use_mmalloc(void);
 
 XBT_PRIVATE size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo);
 
+/* We call dlsym during mmalloc initialization, but dlsym uses malloc.
+ * So during mmalloc initialization, any call to malloc is diverted to a private static buffer.
+ */
+extern uint64_t* mmalloc_preinit_buffer;
+#ifdef __FreeBSD__ /* FreeBSD require more memory, other might */
+#define mmalloc_preinit_buffer_size 256
+#else /* Valid on: Linux */
+#define mmalloc_preinit_buffer_size 32
+#endif
+
 SG_END_DECL
 
 #endif