Make the linux backend more re-entrant safe by using readdir_r() instead
of readdir().

The size calculation for the struct dirent comes from the linux man-page.

Regards,
Bert

---
 src/topology-linux.c |   25 +++++++++++++++++++++----
 1 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/src/topology-linux.c b/src/topology-linux.c
index 50fe2a3..7defcae 100644
--- a/src/topology-linux.c
+++ b/src/topology-linux.c
@@ -10,6 +10,7 @@
 #include <private/private.h>
 #include <private/debug.h>

+#include <stddef.h>
 #include <limits.h>
 #include <stdio.h>
 #include <fcntl.h>
@@ -192,6 +193,13 @@ hwloc_opendir(const char *p, int d 
__hwloc_attribute_unused)
 #endif
 }

+static inline struct dirent *
+hwloc_dirent_alloc(DIR *dir)
+{
+    return malloc(offsetof(struct dirent, d_name) +
+            fpathconf(dirfd(dir), _PC_NAME_MAX) + 1);
+}
+
 int
 hwloc_linux_set_tid_cpubind(hwloc_topology_t topology 
__hwloc_attribute_unused, pid_t tid, hwloc_const_cpuset_t hwloc_set)
 {
@@ -311,6 +319,7 @@ static int
 hwloc_linux_get_proc_tids(DIR *taskdir, unsigned *nr_tidsp, pid_t ** tidsp)
 {
   struct dirent *dirent;
+  struct dirent *dirent_storage;
   unsigned nr_tids = 0;
   unsigned max_tids = 32;
   pid_t *tids;
@@ -324,7 +333,8 @@ hwloc_linux_get_proc_tids(DIR *taskdir, unsigned *nr_tidsp, 
pid_t ** tidsp)

   rewinddir(taskdir);

-  while ((dirent = readdir(taskdir)) != NULL) {
+  dirent_storage = hwloc_dirent_alloc(taskdir);
+  while (readdir_r(taskdir, dirent_storage, &dirent) == 0) {
     if (nr_tids == max_tids) {
       max_tids += 8;
       tids = realloc(tids, max_tids*sizeof(pid_t));
@@ -333,6 +343,7 @@ hwloc_linux_get_proc_tids(DIR *taskdir, unsigned *nr_tidsp, 
pid_t ** tidsp)
       continue;
     tids[nr_tids++] = atoi(dirent->d_name);
   }
+  free(dirent_storage);

   *nr_tidsp = nr_tids;
   *tidsp = tids;
@@ -1166,7 +1177,8 @@ look_sysfsnode(struct hwloc_topology *topology, const 
char *path, unsigned *foun
   dir = hwloc_opendir(path, topology->backend_params.sysfs.root_fd);
   if (dir)
     {
-      while ((dirent = readdir(dir)) != NULL)
+      struct dirent *dirent_storage = hwloc_dirent_alloc(dir);
+      while (readdir_r(dir, dirent_storage, &dirent) == 0)
        {
          unsigned long numnode;
          if (strncmp(dirent->d_name, "node", 4))
@@ -1176,6 +1188,7 @@ look_sysfsnode(struct hwloc_topology *topology, const 
char *path, unsigned *foun
            nbnodes = numnode+1;
        }
       closedir(dir);
+      free(dirent_storage);
     }

   if (nbnodes <= 1)
@@ -1234,7 +1247,8 @@ look_sysfscpu(struct hwloc_topology *topology, const char 
*path)
   dir = hwloc_opendir(path, topology->backend_params.sysfs.root_fd);
   if (dir) {
     struct dirent *dirent;
-    while ((dirent = readdir(dir)) != NULL) {
+    struct dirent *dirent_storage = hwloc_dirent_alloc(dir);
+    while (readdir_r(dir, dirent_storage, &dirent) == 0) {
       unsigned long cpu;
       char online[2];

@@ -1276,6 +1290,7 @@ look_sysfscpu(struct hwloc_topology *topology, const char 
*path)
       hwloc_cpuset_set(cpuset, cpu);
     }
     closedir(dir);
+    free(dirent_storage);
   }

   topology->support.discovery.proc = 1;
@@ -1614,6 +1629,7 @@ hwloc_look_linux(struct hwloc_topology *topology)
   if (nodes_dir) {
     /* Kerrighed */
     struct dirent *dirent;
+    struct dirent *dirent_storage = hwloc_dirent_alloc(nodes_dir);
     char path[128];
     hwloc_obj_t machine;
     hwloc_cpuset_t machine_online_set;
@@ -1625,7 +1641,7 @@ hwloc_look_linux(struct hwloc_topology *topology)

     /* No cpuset support for now.  */
     /* No sys support for now.  */
-    while ((dirent = readdir(nodes_dir)) != NULL) {
+    while (readdir_r(nodes_dir, dirent_storage, &dirent) == 0) {
       unsigned long node;
       if (strncmp(dirent->d_name, "node", 4))
        continue;
@@ -1655,6 +1671,7 @@ hwloc_look_linux(struct hwloc_topology *topology)
                         &machine->attr->machine.dmi_board_name);
     }
     closedir(nodes_dir);
+    free(dirent_storage);
   } else {
     /* Get the machine memory attributes */
     hwloc_get_procfs_meminfo_info(topology, "/proc/meminfo", 
&topology->levels[0][0]->memory);
-- 
tg: (00cf78b..) bw/readdir_r (depends on: master)

Reply via email to