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)