Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ shared memory leak, how to clear shared memory?

I am using Qt and trying to achieve a single instance application by applying this solution in Linux(ubuntu). The problem is that if the application unexpectedly finishes(seg. fault or user kills it) the shared memory remains attached and no other process can create it again. Recall from QSharedMemory doc:

Unix: QSharedMemory "owns" the shared memory segment. When the last thread or process that has an instance of QSharedMemory attached to a particular shared memory segment detaches from the segment by destroying its instance of QSharedMemory, the Unix kernel release the shared memory segment. But if that last thread or process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // Ensure single instanse of Cevirgec application
    QSharedMemory shared(ApplicationConstants::

    if( !shared.create( 512, QSharedMemory::ReadWrite) )
    {
      // QMessageBox msgBox;
      QMessageBox::critical(0, QObject::tr("application is already running!"), QObject::tr("application is already running!"), QMessageBox::Ok, QMessageBox::Ok);
      qCritical() << "application is already running!";

      exit(0);
    }
    else {
        qDebug() << "application staring...";
    }
    return a.exec(); 
}

What solutions can you suggest here? How can I assure that the shared memory is cleared(or whatever verb used generally) after the process eventually finishes. I need something like finally in java all around the main function :/

EDIT: (Solution)

I have achieved the desired behavior by using QSharedMemory and catching SIGSEGV signal then call sharedMemory.detach() in the signal handler.

like image 449
destan Avatar asked Oct 14 '11 20:10

destan


People also ask

How do I clear shared memory in Windows?

On Windows: You can use Microsoft Process Explorer to check the shared memory handle of saposcol and then try to find if another process holds it. You should see that some disp+work has the handle. Kill this and then you should be able to stop saposcol and clean the memory.

What causes memory leaks C?

Memory leaks occur when new memory is allocated dynamically and never deallocated. In C programs, new memory is allocated by the malloc or calloc functions, and deallocated by the free function.

Does Ctrl C free memory?

Most of the memory you allocate will be freed on Ctrl+C. If you see memory usage not return to its prior level, it is almost certainly caused by buffered filesystem blocks.


3 Answers

You can catch the signals that crash your program and use a handler that calls the QSharedMemory destructor.

like image 122
bames53 Avatar answered Oct 09 '22 13:10

bames53


Truth is that if your program needs to be killed or has a segfault, then you cannot really do anything about it. Shared memory is not the best choice for ensuring single instance of appliction under UNIX/Linux. Try using semaphores instead, as they are getting closed as soon as your application terminates.

EDIT:

From documentation of sem_close

All open named semaphores are automatically closed on process termination, or upon execve(2).

I also must add that ensuring single-app contraint might have weird consequences on system like linux - imagine somebody logged via ssh with X tunneling and trying to start your app - if somebody is already using it, it will not start. This will be rather confisunig. You are application developer and should know best if you need per-system per-user or even per-X-session blockade.

If you want to use per-user blockade, then solution might be to add hidden file in user home directory containing current pid. Next application will check for this file, and if it exists AND /proc/[pid]/exe link points to current binary, then return error.

like image 1
j_kubik Avatar answered Oct 09 '22 14:10

j_kubik


You could always run a script after termination of your program to manually clear the shared memory, semaphores, etc. on your system (mine is a Mac Pro running 10.8). I have inserted a script I use for this when running programs that use QSharedMemory, and use it when the program quits unexpectedly and leaves the shared memory instances "hanging".

Keep in mind this will remove all shared memory instances associated with your user name. If you have multiple programs running and using shared memory instances, you should either wait until every program is done, or adjust the script as needed to only delete the shared memory instances that were created by your program.

#!/bin/bash

ME=$(whoami)

IPCS_S=$(ipcs -s | grep $ME | sed "s/  / /g" | cut -f2 -d " ")
IPCS_M=$(ipcs -m | grep $ME | sed "s/  / /g" | cut -f2 -d " ")
IPCS_Q=$(ipcs -q | grep $ME | sed "s/  / /g" | cut -f2 -d " ")

echo "Clearing Semaphores"
for id in $IPCS_S
do
    ipcrm -s $id
done

echo "Clearing Shared Memory"
for id in $IPCS_M 
do
    ipcrm -m $id
done

echo "Clearing Message Queues"
for id in $IPCS_Q
do
    ipcrm -q $id
done
like image 1
rvijay007 Avatar answered Oct 09 '22 15:10

rvijay007