2011-10-14 197 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