2011-10-14 147 views
5

我使用Qt和努力实现由应用this解决方案的Linux(Ubuntu的)一个单实例应用程序。问题是,如果应用程序意外完成(seg。fault或用户终止它),共享内存将保持连接状态,并且其他进程不能再次创建它。从QSharedMemory回收文档:C++共享内存泄漏,如何清除共享内存?

Unix:QSharedMemory“拥有”共享内存段。当最后一个 线程或进程的QSharedMemory实例连接到一个 特定共享内存段从该段分离 销毁它的QSharedMemory实例时,Unix内核释放 共享内存段。但是,如果最后一个线程或进程崩溃 而不运行QSharedMemory析构函数,共享内存 段生存的崩溃。

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(); 
} 

你可以建议在这里有什么解决办法?我怎样才能确保在进程最终完成后清除共享内存(或通常使用的任何动词)。我需要在Java类似finally各地主要功能:在(解决方案)

我以QSharedMemory和捕获SIGSEGV信号,然后调用sharedMemory.detach达到了预期的行为():/

编辑信号处理程序。

+0

您可能不应该试图创建一个与操作系统和用户期望应用程序行为不同的应用程序。如果操作系统的标准行为使得用户希望能够启动多个实例,如在Windows和Linux上,那么他们应该能够。如果标准行为是强制一个实例,就像在Mac上一样,然后让操作系统自己执行。 – bames53

+2

那么在操作系统中没有这种行为的标准。它完全取决于应用程序 – destan

+0

bames53:有大量应用程序只允许您启动一个实例,有时这是合乎逻辑的事情。 – rubenvb

回答

4

可以赶上你的程序崩溃和使用,调用析构函数QSharedMemory处理程序的信号。

+0

我可以手动调用析构函数吗 – destan

+0

是的,例如对于Foo类的对象f:'f。〜Foo();'。但是,只有在语言不会自动调用析构函数的情况下,您也必须这样做。 – bames53

+0

是的,你可以 - 但我不知道它是否可以依赖于任何qt相关的信号处理程序,因为这样的处理程序应该是自包含的,而不是在程序中的任何其他中继。 –

1

事实是,如果你的程序需要被杀死或有段错误,那么你真的不能做任何事情。在UNIX/Linux下,共享内存不是确保单个应用程序实例的最佳选择。尝试使用信号量,因为只要应用程序终止,它们就会关闭。

编辑:

sem_close

所有文档均开放命名信号自动关闭工艺 终止,或基于的execve(2)。

我还要补充一点,确保单应用contraint可能对系统如Linux怪异的后果 - 想象通过与X隧道SSH登录和某人试图启动您的应用程序 - 如果有人已经在使用它,它不会开始。这将是相当confisunig。你是应用程序开发人员,如果你需要每个系统每个用户甚至每个X会话封锁,你应该知道的最好。

如果你想为每个用户都封锁,那么解决方案可能是添加隐藏文件包含当前PID用户主目录。下一个应用程序将检查此文件,如果存在AND/proc/[pid]/exe链接指向当前二进制文件,则返回错误。

+0

但是我认为我需要一个系统范围的信号量吗? – destan

+0

命名信号是准确的 –

+0

但有同样的问题的时候,如果坠毁旗语仍然取得 – destan

1

你总是可以运行一个脚本程序结束后手动清除您的系统上的共享内存,信号等(我的是一个Mac Pro的运行10.8)。在运行使用QSharedMemory的程序时,我插入了一个用于此目的的脚本,并在程序意外退出并使共享内存实例“挂起”时使用它。

请记住,这将删除与您的用户名关联的所有共享内存实例。如果您有多个运行和使用共享内存实例的程序,则应等到每个程序都完成后,或者根据需要调整脚本,以仅删除由程序创建的共享内存实例。

#!/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