Reputation: 61
When I have several processes going on using a shared memory, and I detach all of them but one.
shmctl()
(with that process)?Upvotes: 3
Views: 4048
Reputation: 15408
The behavior of shmctl(,... IPC_RMID, ...)
is not explicitly defined by SingleUnix:
Remove the shared memory identifier specified by
shmid
from the system and destroy the shared memory segment andshmid_ds
data structure associated with it.
One could argue, that IPC_RMID
should invalidate all references to a shared memory segment immediately. In practice, the removal is delayed until the last process detaches by most implementations, which is more in line with the typical semantics one would expect e.g. from a FIFO. The name is removed, but the real kernel object only goes away once all references are released.
On Linux, destruction is lazy, the segment will only be destroyed once the last process detaches:
The segment will only actually be destroyed after the last process detaches it (i.e., when the shm_nattch member of the associated structure shmid_ds is zero).
The same behavior is present on FreeBSD:
The removal will not take effect until all processes having attached the segment have exited.
Solaris has it similarly, but explained backwards:
If the segment is not attached to any process when
IPC_RMID
is invoked, it will be destroyed immediately.
Upvotes: 1
Reputation: 755094
The manual entry for shmctl()
doesn't say anything about 'at most one process using it' or 'no processes attached to it'. However, the system can't completely disrupt already running processes that are attached to the shared memory segment.
You only need the shmid
(shared memory segment ID) returned by shmget()
; you don't need the shared memory to be attached (so you could already have run shmdt()
).
Testing on a Mac (macOS Sierra 10.12.3, GCC 6.3.0) with code derived from a previous question (Making a shared data structure in C), I added an option -t time
to make the process sleep for a specifiable period. Then I created a shared memory segment and left the process holding it open. I used ipcs -m
to see that the segment existed. Then I deleted the segment; it was successful. Rechecking with ipcs -m
, the segment had changed from shared to IPC_PRIVATE
. When the sleeping process completed, the shared memory segment was automatically deleted (as private segments always are).
$ shm-master -f shm-master -s 1024 -x -t 120 &
[1] 14392
$ ID: 0, File: shm-master
Key: 0x00041BF7
ShmID: 1441795
Shared memory allocated at 0x10F2B4000
Sleeping for 120 seconds
$ ipcs -m
IPC status from <running system> as of Wed Feb 15 11:56:37 PST 2017
T ID KEY MODE OWNER GROUP
Shared Memory:
m 65536 0x00fedc64 --rw-rw-rw- root wheel
m 65537 0x0052e2c1 --rw------- postgres daemon
m 65538 0x52042973 --rw------- root wheel
m 1441795 0x00041bf7 --rw------- jleffler staff
$ shm-master -f shm-master -s 1024 -d
ID: 0, File: shm-master
Key: 0x00041BF7
ShmID: 1441795
Shared memory removed
$ ipcs -m
IPC status from <running system> as of Wed Feb 15 11:56:47 PST 2017
T ID KEY MODE OWNER GROUP
Shared Memory:
m 65536 0x00fedc64 --rw-rw-rw- root wheel
m 65537 0x0052e2c1 --rw------- postgres daemon
m 65538 0x52042973 --rw------- root wheel
m 1441795 0x00000000 --rw------- jleffler staff
$ sleep 120; ipcs -m
Detached from shared memory
[1]+ Done shm-master -f shm-master -s 1024 -x -t 120
IPC status from <running system> as of Wed Feb 15 11:58:57 PST 2017
T ID KEY MODE OWNER GROUP
Shared Memory:
m 65536 0x00fedc64 --rw-rw-rw- root wheel
m 65537 0x0052e2c1 --rw------- postgres daemon
m 65538 0x52042973 --rw------- root wheel
$
Whether this is what happens on other systems, I'm not sure, but it looks like plausible behaviour. Something similar is likely to occur.
Incidentally, running one process to create the segment and a second to just attach to it, both running in sleep mode, didn't really change the observed results. The shared memory segment key changed to 0, the processes were unaffected, and the segment was deleted after both had completed.
Upvotes: 2