https://gcc.gnu.org/g:936b982b9edf19ce66a42f6a5f3e4a50b160facc
commit r17-5282-g936b982b9edf19ce66a42f6a5f3e4a50b160facc Author: Jerry DeLisle <[email protected]> Date: Mon Oct 5 11:06:08 2026 -0700 libgfortran: [PR127753] caf_shmem: do not leak the shared memory object When the supervisor was stopped by a signal, for example by a timeout or ^C, it exited without unlinking the shared memory object, so the object was left behind in /dev/shm. The supervisor now passes the descriptor of the object to the images and removes its name right after creating it, so that the object goes away with the last process however the program ends. The mapping is excluded from core dumps, because the kernel dumps an unlinked object like anonymous memory, which would write out the whole pool. Assisted-by: Claude Opus 5.5 PR libfortran/127753 libgfortran/ChangeLog: * caf/shmem/shared_memory.c (ENV_FD): New. (shared_memory_init): Pass the descriptor to the images through ENV_FD and unlink the object. Use the inherited descriptor in an image. Exclude the mapping from core dumps. (shared_memory_cleanup): Do not unlink an unlinked object. Diff: --- libgfortran/caf/shmem/shared_memory.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/libgfortran/caf/shmem/shared_memory.c b/libgfortran/caf/shmem/shared_memory.c index cbe4b0451a6b..f111e82da170 100644 --- a/libgfortran/caf/shmem/shared_memory.c +++ b/libgfortran/caf/shmem/shared_memory.c @@ -58,6 +58,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see static const char *ENV_PPID = "GFORTRAN_SHMEM_PPID"; static const char *ENV_BASE = "GFORTRAN_SHMEM_BASE"; +#if defined(HAVE_MMAP) && defined(HAVE_SETENV) +/* The descriptor of the shared memory object the images inherit. */ +static const char *ENV_FD = "GFORTRAN_SHMEM_FD"; +#endif void shared_memory_set_env (pid_t pid) @@ -181,6 +185,17 @@ shared_memory_init (shared_memory_act *mem, size_t size) perror ("resizing shared memory segment failed."); exit (1); } +#ifdef HAVE_SETENV + /* Pass the descriptor to the images and remove the name, so that the + object goes away with the last process however the program ends. */ + if (fcntl (mem->shm_fd, F_SETFD, 0) == 0) + { + char val[20]; + snprintf (val, 20, "%d", mem->shm_fd); + setenv (ENV_FD, val, 1); + shm_unlink (shm_name); + } +#endif #elif defined(WIN32) mem->shm_fd = CreateFileMapping (INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, @@ -216,7 +231,13 @@ shared_memory_init (shared_memory_act *mem, size_t size) else { #ifdef HAVE_MMAP - mem->shm_fd = shm_open (shm_name, O_RDWR, 0600); +#ifdef HAVE_SETENV + const char *fd_val = getenv (ENV_FD); + if (fd_val) + mem->shm_fd = atoi (fd_val); + else +#endif + mem->shm_fd = shm_open (shm_name, O_RDWR, 0600); if (mem->shm_fd == -1) { perror ("opening shared memory segment failed."); @@ -246,6 +267,11 @@ shared_memory_init (shared_memory_act *mem, size_t size) perror ("mmap failed"); exit (1); } +#ifdef MADV_DONTDUMP + /* Keep the unlinked object, which counts as anonymous shared memory, out + of core dumps. */ + madvise (mem->glbl.base, size, MADV_DONTDUMP); +#endif #elif defined(WIN32) mem->glbl.base = (LPTSTR) MapViewOfFileEx (mem->shm_fd, FILE_MAP_ALL_ACCESS, 0, 0, @@ -296,7 +322,11 @@ shared_memory_cleanup (shared_memory_act *mem) { perror ("closing shm file handle failed. Trying to continue..."); } - if (this_image.image_num == -1) + if (this_image.image_num == -1 +#ifdef HAVE_SETENV + && !getenv (ENV_FD) +#endif + ) { char shm_name[SHM_NAME_MAX];
