GNOME Bugzilla – Bug 609026
leaks shared memory
Last modified: 2010-02-10 18:41:41 UTC
Shared memory is not released when gimp exits. This is a big problem when a script calls gimp many times, where the system eventually runs out of shared memory.
Hi and thanks for the bug report! Please provide step-by-step instructions, preferably that includes a script, on how to reproduce the problem.
This is the way to notice the problem on Solaris. Each time gimp is run, a block of shared memory is allocated and not freed when gimp exits, as indicated by the ipcs command. Each invocation of gimp below did nothing but start up and exit cleanly. The shared memory is never released and must either be manually released with the ipcrm command or the system must be rebooted. Any script which runs multiple versions of gimp or gimp-console will quickly consume all of the available shared memory resources. #ipcs IPC status from <running system> as of Thu Feb 4 22:54:21 PST 2010 T ID KEY MODE OWNER GROUP Message Queues: Shared Memory: m 0 0x0 --rw-rw-rw- root root Semaphores: s 0 0xcbc384f8 --ra------- george white #gimp #ipcs IPC status from <running system> as of Thu Feb 4 22:54:43 PST 2010 T ID KEY MODE OWNER GROUP Message Queues: Shared Memory: m 16777268 0x0 --rw------- george white m 0 0x0 --rw-rw-rw- root root Semaphores: s 0 0xcbc384f8 --ra------- george white #gimp #gimp #ipcs IPC status from <running system> as of Thu Feb 4 22:55:23 PST 2010 T ID KEY MODE OWNER GROUP Message Queues: Shared Memory: m 16777274 0x0 --rw------- george white m 16777271 0x0 --rw------- george white m 16777268 0x0 --rw------- george white m 0 0x0 --rw-rw-rw- root root Semaphores: s 0 0xcbc384f8 --ra------- george white #
If Solaris doesn't clean up after processes that exit, that seems to be a pretty severe bug in Solaris then. Anyway, we are accepting patches, tested on Solaris, to address this problem.
It's my understanding that it's the responsibility of the processes sharing a resource to mutually agree to destroy it. The way to do this is with shmctl(id, IPC_RMID, NULL), where id is the identifier of the shared memory. The kernel isn't supposed to reclaim this automatically on process death, because the contents of shared memory should be able to persist, even if no processes are actively referencing it. Only if all parties interested in the shared resource call shmctl with the IPC_RMID command will the shared resource be freed when all of the acive processes have completed. Linux should behave the same way and in any event, calling shmctl from Linux will have the desired effect and is a more robust implementation. From the Solaris man page for shmop: Shared memory segments must be explicitly removed after the last reference to them has been removed.
The bug is in gimp. We free SHM in gimp_plug_in_manager_finalize(), but this function is never called in stable GIMP versions, only the "exit" apparatus runs, calls gimp_plug_in_manager_exit(), and in the end terminates the process to save time.
To be precise, we rely on the ability to do shmctl (id, IPC_RMID, NULL); right after creating and attaching to the shared memory segment. On Linux, this is a nice way to make sure the SHM segment goes away after the last process using it exits. It's not portable however... man shmat: On Linux, it is possible to attach a shared memory segment even if it is already marked to be deleted. However, POSIX.1-2001 does not specify this behavior and many other implementations do not support it.
Fixed in master and 2-6: commit cb41897d21161687c7003d021ddcd4218e57609a Author: Michael Natterer <mitch@gimp.org> Date: Wed Feb 10 19:37:46 2010 +0100 Bug 609026 - leaks shared memory Move calling gimp_plug_in_shm_free() from gimp_plug_in_manager_finalize() to gimp_plug_in_manager_exit() so it's also called in stable GIMP releases which simply call exit() at some point instead of taking the time to shut down everything completely. (cherry picked from commit 9a4bf10d30d3ace506caa2196e8f56b369bfab86) app/plug-in/gimppluginmanager.c | 15 +++++++++------ 1 files changed, 9 insertions(+), 6 deletions(-)