我正在使用Qt并尝试通过在 Linux(ubuntu)中应用this解决方案来实现单实例应用程序。问题是,如果应用程序意外完成(seg。错误或用户杀死它),共享内存将保持连接状态,其他任何进程都无法再次创建它。回想一下QSharedMemory doc:
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 :(得分:5)
您可以捕获导致程序崩溃的信号,并使用调用QSharedMemory析构函数的处理程序。
答案 1 :(得分:1)
事实是,如果您的程序需要被杀死或有段错误,那么您无法真正做任何事情。共享内存不是确保UNIX / Linux下单个应用程序实例的最佳选择。请尝试使用信号量,因为它们会在应用程序终止后立即关闭。
编辑:
的文档所有打开的命名信号量都会在进程中自动关闭 终止,或执行(2)。
我还必须补充一点,确保单应用程序约束可能会对像linux这样的系统产生奇怪的后果 - 想象有人通过ssh使用X隧道进行登录并尝试启动你的应用程序 - 如果某人已经在使用它,它将无法启动。这将是相当混乱的。您是应用程序开发人员,如果您需要每个系统的每个用户甚至每个X-session阻止,那么您应该最了解。
如果您想使用每用户封锁,那么解决方案可能是在包含当前pid的用户主目录中添加隐藏文件。下一个应用程序将检查此文件,如果它存在并且/ proc / [pid] / exe链接指向当前二进制文件,则返回错误。
答案 2 :(得分:1)
您可以在程序终止后运行脚本,以手动清除系统上的共享内存,信号量等(我的是运行10.8的Mac Pro)。我在运行使用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