2011-10-14 25 views
5

私はQtを使用しており、thisソリューションをLinux(ubuntu)に適用して、単一のインスタンスアプリケーションを実現しようとしています。問題は、アプリケーションが予期せず終了した場合(seg。faultまたはuserがkillする)、共有メモリは接続されたままであり、他のプロセスが再びそれを作成できないということです。 QSharedMemoryからリコールdoc: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ようなものが必要:/

EDIT:(ソリューション)

私はQSharedMemoryを使用し、SIGSEGVシグナルをキャッチすることにより、目的の動作を達成した後、(sharedMemory.detachを呼び出す)でシグナルハンドラ

+0

OSとユーザーがAppsの動作を期待する方法とは異なる動作をするアプリを作ろうとしないでください。 OSの標準的な動作が、WindowsやLinuxのように複数のインスタンスを起動できると想定されるようなものであれば、できるはずです。標準の動作がMacの場合と同じように単一のインスタンスを強制することである場合は、OSにそれを強制させます。 – bames53

+2

OSにこのような振る舞いの標準はありません。それは完全にアプリケーションに依存しています – destan

+0

bames53:1つのインスタンスを起動させるだけのアプリがたくさんあります。 – rubenvb

答えて

4

プログラムをクラッシュさせるシグナルをキャッチし、QSharedMemoryデストラクタを呼び出すハンドラを使用できます。

+0

デストラクタを手動で呼び出すことはできますか? – destan

+0

はい。クラスFooのオブジェクトfに対して:f。〜Foo(); '。しかし、言語がデストラクタを自動的に呼び出さないような状況でのみ行う必要があります。 – bames53

+0

はい、できますが、シグナルハンドラでqt関連のものがあるかどうかはわかりません。そのようなハンドラは自己完結型で、プログラム内の他のものにはリレーしないでください。 –

1

真実は、あなたのプログラムを殺す必要がある場合、またはsegfaultがある場合、本当に何もできないということです。共有メモリは、UNIX/Linuxでの単一インスタンスのアプリケーションを保証するための最良の選択ではありません。アプリケーションが終了するとすぐに閉じられるので、代わりにセマフォを使用してみてください。

EDIT:sem_close

すべてのドキュメントから

は、名前付きセマフォは自動的に(2)プロセス 終了時に、またはexecveの時に閉鎖されているオープン。

私はまた、単一のアプリcontraintを確保することはLinuxのようなシステム上で奇妙な結果をもたらす可能性があることを追加する必要があります - 誰かがXトンネリングとssh経由でログインしてアプリを起動しようと想像する - 誰かがすでにそれを使用している場合、それはしません開始。これはむしろconfisunigになります。あなたはアプリケーション開発者であり、システムごとに、あるいはXセッションごとにブロックする必要がある場合には、最もよく知っておくべきです。

ユーザーごとの封鎖を使用する場合は、現在のpidを含むユーザーのホームディレクトリに隠しファイルを追加することがあります。次のアプリケーションはこのファイルをチェックし、存在する場合は/ proc/[pid]/exeリンクが現在のバイナリを指している場合はエラーを返します。

+0

しかし、私はシステム全体のセマフォーが必要でしょうか? – destan

+0

名前付きセマフォは –

+0

正確にはなく、墜落したセマフォが、私はsharedMemory.detach() をQSharedMemoryを組み合わせ、その後、呼び出しSIGSEGVシグナルをキャッチすることにより、目的の動作を達成している。しかし、あなたの編集中にあなたがいることを私に思い出させる – 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