Skip to content
Advertisement

Using shared memory and how to correctly unallocate a space with IPC_RMID

I have 2 applications running on my linux box, a server and a client. My server and client examples I am working with is from Dave Marshalls examples.

Everything works well, but when I try this in my background process and I want to extend my original segment (perhaps due to an application upgrade in the future) I either have to change my key or somehow pass the shmctl(shmid, IPC_RMID, 0) call in my app. Since my app cannot exit graciously and I cannot set this right at the beginning after allocation (since no other app will be able to use this shared mem space once it has been marked for deletion) I have no way of cleaning this space up.

The best I have come up with so far is to shmget my old section, check if it exists, clear it if it does then allocate it to a high value. This would look like:

void init_shared_mem(void)
{
    int shmid;
    key_t key = 0x1235; //key to be passed to shmget()
    int oldSize = 27;
    int newSize = 28;
    char * shm;

    //check to see if an allocation exists
    if ((shmid = shmget(key, oldSize, IPC_CREAT | 0666)) < 0)
    {
        perror("shmget: shmget failed");
    }
    //unallocate it if it does
    else if (shmctl(shmid , IPC_RMID , 0) == -1)
    {
        perror("shmid");
    }


    //reallocate new section
    if ((shmid = shmget(key, newSize, IPC_CREAT | 0666)) < 0)
    {
        perror("shmget: shmget failed");
        exit(1);
    }

    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1)
    {
        perror("shmat");
        exit(1);
    }
}

Other SO questions either don’t seem to touch on this or bring it up as a possible concern. Is there a better way to do this that I am missing or perhaps I can simply reallocate it to a higher value instead of clearing it?

Advertisement

Answer

You don’t say which operating system you are running on. If you’re on Linux, OpenBSD 5.1 or later or other operating systems configured a particular way you may well be able to attach after having done IPC_RMID so long as something is still attached to it but bear in mind this behaviour is not portable (here’s an older examination of IPC_RMID behaviour on different OSes). Without this behaviour it’s going to be difficult to avoid stale segments being left behind if your program crashes (aka “doesn’t exit graciously”) when it’s the last thing attached to the segment.

I should also note that your question sounds similar to the problem discussed over in Options for robust process cleanup over on the UNIX Socket FAQ forum where suggestions included: use Linux’s IPC_RMID behaviour, have a monitoring parent process check for process death and do cleanup.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement