Reputation: 732
I'm having issues using shmget() to manage memory segments. According to the man page, if both IPC_CREAT and IPC_EXCL flags are set, shmget should fail if it is asked to create a segment for a key that already exists.
What I'm seeing is that shmget creates a new segment for the same key (with a new shmid) regardless. The code below illustrates this issue. I'm running two instances of it, one in 'creator' mode, one in 'client' mode.
./test 10 0
./test 10 1
The creator allocates a memory segment for key=10, then attaches to it. The client also attaches to the segment. Running ipcs -m I can see that the segment exists and that two processes are attached to it.
Then I make the creator destroy the segment, and as expected ipcs shows that it is marked for destruction, with 1 process still attached. What's strange, is that if I start the creator again, with the same key, it creates a new segment instead of failing since a segment already exists?
Thanks for your help!
#include <sys/shm.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <stdexcept>
using namespace std;
int main( int argc, char** argv )
{
cout << "usage: " << argv[0] << " <key> <mode (0=creator 1=client)>" << endl;
if ( argc < 3 ) return 0;
int key = atoi( argv[1] );
int mode = atoi( argv[2] );
cout << "key=" << key << endl;
cout << "mode=" << mode << endl;
char c;
int shmid=-1;
int size = 100; // bytes
try
{
if ( mode == 0 ) // creator
{
cout << "creating segment" << endl;
int flags = ( IPC_CREAT | IPC_EXCL | 0666 );
shmid = shmget( key, size, flags );
if ( shmid== -1 )
throw runtime_error("failed to create segment");
cout << "created: shmid=" << shmid << endl;
}
else if ( mode == 1 )
{
shmid = shmget( key, 0, 0 );
if ( shmid== -1 )
throw runtime_error("failed to load");
cout << "loaded: shmid=" << shmid << endl;
}
cout << "attach? (press key to continue)" << endl;
cin >> c;
void* data = shmat( shmid, NULL, 0 );
if ( data == (void *) -1 )
throw runtime_error("failed to attach");
cout << "attached to id=" << shmid << endl;
cout << "destroy? (press key to continue)" << endl;
cin >> c;
if ( shmctl( shmid, IPC_RMID, NULL ) == -1 )
throw runtime_error("failed to destroy");
cout << "destroyed" << endl;
}
catch( const exception& e )
{
cout << e.what() << " errno=" << errno << endl;
}
}
Upvotes: 0
Views: 7006
Reputation: 74485
You should pay closer attention to the output of ipcs
. Using your example code with a key of 10
.
The server has created the segment:
$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x0000000a 1470791680 hristo 666 100 1
The client is attached, the server has marked the segment for destruction:
$ ipcs -m
------ Shared Memory Segments --------
key shmid owner perms bytes nattch status
0x00000000 1470791680 hristo 666 100 1 dest
^^^^^^^^^^
As no new processes are expected to be able to find and attach such segments by their key, the key is being zeroed out. That's why you can create a new one with the same key.
Upvotes: 4