From c6df957538ffd21cb25ddc16885d057e92df8056 Mon Sep 17 00:00:00 2001
From: "Peter W. Draper" <p.w.draper@durham.ac.uk>
Date: Mon, 29 Jan 2024 14:22:09 +0000
Subject: [PATCH] Resolve memory leak in repart_edge_metis src/partition.c:1635

---
 src/partition.c | 28 +++++++++++++++++++++++-----
 src/partition.h |  2 ++
 swift.c         |  1 +
 swift_fof.c     |  3 ++-
 4 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/src/partition.c b/src/partition.c
index 2030451dad..e4d544d4c5 100644
--- a/src/partition.c
+++ b/src/partition.c
@@ -2063,7 +2063,7 @@ void partition_init(struct partition *partition,
 
 #ifdef WITH_MPI
 
-/* Defaults make use of METIS if available */
+  /* Defaults make use of METIS if available */
 #if defined(HAVE_METIS) || defined(HAVE_PARMETIS)
   const char *default_repart = "fullcosts";
   const char *default_part = "edgememory";
@@ -2079,6 +2079,10 @@ void partition_init(struct partition *partition,
   factor(partition->grid[0] * partition->grid[1], &partition->grid[1],
          &partition->grid[0]);
 
+  /* Initialise the repartition celllist. */
+  repartition->ncelllist = 0;
+  repartition->celllist = NULL;
+
   /* Now let's check what the user wants as an initial domain. */
   char part_type[20];
   parser_get_opt_param_string(params, "DomainDecomposition:initial_type",
@@ -2187,10 +2191,6 @@ void partition_init(struct partition *partition,
   repartition->itr =
       parser_get_opt_param_float(params, "DomainDecomposition:itr", 100.0f);
 
-  /* Clear the celllist for use. */
-  repartition->ncelllist = 0;
-  repartition->celllist = NULL;
-
   /* Do we have fixed costs available? These can be used to force
    * repartitioning at any time. Not required if not repartitioning.*/
   repartition->use_fixed_costs = parser_get_opt_param_int(
@@ -2219,6 +2219,24 @@ void partition_init(struct partition *partition,
 #endif
 }
 
+/**
+ * @brief Clean up any allocated resources.
+ *
+ * @param partition The #partition
+ * @param repartition The #repartition
+ */
+void partition_clean(struct partition *partition,
+                     struct repartition *repartition) {
+#ifdef WITH_MPI
+  /* Only the celllist is dynamic. */
+  if (repartition->celllist != NULL) free(repartition->celllist);
+
+  /* Zero structs for reuse. */
+  bzero(partition, sizeof(struct partition));
+  bzero(repartition, sizeof(struct repartition));
+#endif
+}
+
 #ifdef WITH_MPI
 /**
  * @brief Set the fixed costs for repartition using METIS.
diff --git a/src/partition.h b/src/partition.h
index 8f6dbbd148..8c2ac8acce 100644
--- a/src/partition.h
+++ b/src/partition.h
@@ -83,6 +83,8 @@ void partition_init(struct partition *partition,
                     struct repartition *repartition,
                     struct swift_params *params, int nr_nodes);
 
+void partition_clean(struct partition *partition, struct repartition *repartition);
+
 /* Dump/restore. */
 void partition_store_celllist(struct space *s, struct repartition *reparttype);
 void partition_restore_celllist(struct space *s,
diff --git a/swift.c b/swift.c
index 1851ad3868..038f078a68 100644
--- a/swift.c
+++ b/swift.c
@@ -1935,6 +1935,7 @@ int main(int argc, char *argv[]) {
   free(output_options);
 
 #ifdef WITH_MPI
+  partition_clean(&initial_partition, &reparttype);
   if ((res = MPI_Finalize()) != MPI_SUCCESS)
     error("call to MPI_Finalize failed with error %i.", res);
 #endif
diff --git a/swift_fof.c b/swift_fof.c
index 0930426f48..784c6f4d1f 100644
--- a/swift_fof.c
+++ b/swift_fof.c
@@ -373,8 +373,8 @@ int main(int argc, char *argv[]) {
   }
 
   /* Prepare the domain decomposition scheme */
-  struct repartition reparttype;
 #ifdef WITH_MPI
+  struct repartition reparttype;
   struct partition initial_partition;
   partition_init(&initial_partition, &reparttype, params, nr_nodes);
 
@@ -777,6 +777,7 @@ int main(int argc, char *argv[]) {
   free(output_options);
 
 #ifdef WITH_MPI
+  partition_clean(&initial_partition, &reparttype);
   if ((res = MPI_Finalize()) != MPI_SUCCESS)
     error("call to MPI_Finalize failed with error %i.", res);
 #endif
-- 
GitLab