From 97900ebfb0192130823dce8aa8f36916313a1c18 Mon Sep 17 00:00:00 2001 From: Sitsofe Wheeler Date: Tue, 24 Jan 2017 06:31:58 +0000 Subject: [PATCH] shm: have os remove shared memory if fio dies unexpectedly When fio doesn't exit cleanly shared memory segments are left behind on those platforms where shared memory is supported. Due to how fio manages shared memory lifetime we can combat the above by marking the shared memory segment as removed shortly after we attach to it for the first time if the OS offers both the following (non-standard) behaviours: 1. A shared memory segment marked for removal with IPC_RMID isn't destroyed until all processes have detached from it. 2. After 1. has occurred it is still possible to (re)attach to the marked-for-removal shared memory segment. Linux has always done the above so enable the workaround there. OpenBSD switched to having the above behaviours in 5.1 (see shmctl in https://www.openbsd.org/plus51.html ) so add a comment about it in os/os-openbsd.h . FreeBSD only has the above behaviours if kern.ipc.shm_allow_removed (introduced in 5.2) is 1 and this only became the default in FreeBSD 11 (https://svnweb.freebsd.org/base?view=revision&revision=289112 ) so add a comment in os/os-freebsd.h . DragonFly also has the FreeBSD flag but at the time of writing it defaults to 0 so add a comment to os/os-dragonfly.h . There's a nice (if dated) post discussing how IPC_RMID behaves on various OSes in https://www.cygwin.com/ml/cygwin/2007-11/msg00078.html ("Re: cygwin stable and cvs snapshot - fork() bug"). While fio doesn't support the Cygwin "OS", Cygwin itself has the kern.ipc.shm_allow_removed option in a config file and defaults it to no. --- init.c | 3 +++ os/os-dragonfly.h | 2 ++ os/os-freebsd.h | 3 +++ os/os-linux.h | 1 + os/os-openbsd.h | 3 +++ 5 files changed, 12 insertions(+) diff --git a/init.c b/init.c index c3cc3e54..34ed20f1 100644 --- a/init.c +++ b/init.c @@ -356,6 +356,9 @@ static int setup_thread_area(void) perror("shmat"); return 1; } +#ifdef FIO_HAVE_SHM_ATTACH_REMOVED + shmctl(shm_id, IPC_RMID, NULL); +#endif #endif memset(threads, 0, max_jobs * sizeof(struct thread_data)); diff --git a/os/os-dragonfly.h b/os/os-dragonfly.h index c7998177..5e94855c 100644 --- a/os/os-dragonfly.h +++ b/os/os-dragonfly.h @@ -24,6 +24,8 @@ #define FIO_HAVE_GETTID #define FIO_HAVE_CPU_AFFINITY #define FIO_HAVE_IOPRIO +/* Only have attach-to-open-removed when kern.ipc.shm_allow_removed is 1 */ +#undef FIO_HAVE_SHM_ATTACH_REMOVED #define OS_MAP_ANON MAP_ANON diff --git a/os/os-freebsd.h b/os/os-freebsd.h index ac408c9d..aa90954d 100644 --- a/os/os-freebsd.h +++ b/os/os-freebsd.h @@ -22,6 +22,9 @@ #define FIO_HAVE_TRIM #define FIO_HAVE_GETTID #define FIO_HAVE_CPU_AFFINITY +/* Only have attach-to-open-removed when kern.ipc.shm_allow_removed is 1 */ +#undef FIO_HAVE_SHM_ATTACH_REMOVED + #define OS_MAP_ANON MAP_ANON diff --git a/os/os-linux.h b/os/os-linux.h index 06235abc..18298297 100644 --- a/os/os-linux.h +++ b/os/os-linux.h @@ -41,6 +41,7 @@ #define FIO_HAVE_GETTID #define FIO_USE_GENERIC_INIT_RANDOM_STATE #define FIO_HAVE_PWRITEV2 +#define FIO_HAVE_SHM_ATTACH_REMOVED #ifdef MAP_HUGETLB #define FIO_HAVE_MMAP_HUGE diff --git a/os/os-openbsd.h b/os/os-openbsd.h index 3343cbdf..47005721 100644 --- a/os/os-openbsd.h +++ b/os/os-openbsd.h @@ -25,6 +25,9 @@ #undef FIO_HAVE_CPU_AFFINITY /* XXX notyet */ +/* Only OpenBSD 5.1 and above have attach-to-open-removed semantics */ +#undef FIO_HAVE_SHM_ATTACH_REMOVED + #define OS_MAP_ANON MAP_ANON #ifndef PTHREAD_STACK_MIN -- 2.25.1