2011-10-14 27 views
5

मैं क्यूटी का उपयोग कर रहा हूं और thisलिनक्स (उबंटू) में समाधान लागू करके एक एकल इंस्टेंस एप्लिकेशन प्राप्त करने का प्रयास कर रहा हूं। समस्या यह है कि यदि एप्लिकेशन अप्रत्याशित रूप से खत्म हो जाता है (seg। गलती या उपयोगकर्ता इसे मारता है) साझा स्मृति संलग्न रहती है और कोई अन्य प्रक्रिया इसे फिर से बना सकती है। QSharedMemory दस्तावेज़ से याद रखें:सी ++ साझा स्मृति रिसाव, साझा स्मृति को कैसे साफ़ करें?

यूनिक्स: QSharedMemory साझा स्मृति खंड "का मालिक है"। जब धागा या प्रक्रिया जिसमें से जुड़े QSharedMemory का उदाहरण है, विशेष साझा मेमोरी सेगमेंट से सेगमेंट से अलग हो जाता है, तो QSharedMemory के उदाहरण को नष्ट कर देता है, यूनिक्स कर्नेल साझा मेमोरी सेगमेंट जारी करता है। लेकिन अगर वह अंतिम धागा या प्रक्रिया को 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(); 
} 

क्या समाधान आप यहाँ का सुझाव कर सकते हैं? अंततः प्रक्रिया समाप्त होने के बाद मैं कैसे आश्वस्त कर सकता हूं कि साझा स्मृति साफ़ हो जाती है (या आमतौर पर जो भी क्रिया का उपयोग किया जाता है)। में (समाधान)

मैं QSharedMemory का उपयोग करने और पकड़ने SIGSEGV संकेत तो sharedMemory.detach फोन द्वारा वांछित व्यवहार हासिल किया():/

संपादित करें: मैं सभी मुख्य कार्य के आसपास जावा में finally की तरह कुछ की जरूरत है सिग्नल हैंडलर।

+0

शायद आपको ऐसा ऐप बनाने की कोशिश नहीं करनी चाहिए जो ओएस और उपयोगकर्ताओं को ऐप्स से व्यवहार करने की अपेक्षा से अलग तरीके से व्यवहार करे। यदि ओएस के लिए मानक व्यवहार ऐसा है कि उपयोगकर्ता विंडोज और लिनक्स के रूप में कई उदाहरण लॉन्च करने में सक्षम होने की उम्मीद करते हैं, तो उन्हें बस सक्षम होना चाहिए। यदि मानक व्यवहार मैक पर एक उदाहरण को मजबूर करना है, तो ओएस को स्वयं को लागू करने दें। – bames53

+2

अच्छी तरह से ओएस में ऐसे व्यवहारों के लिए कोई मानक नहीं है। यह पूरी तरह से आवेदन निर्भर है – destan

+0

bames53: ऐसे कई ऐप्स हैं जो केवल आपको एक उदाहरण शुरू करने देते हैं, और कभी-कभी यह करने के लिए तार्किक बात है। – rubenvb

उत्तर

4

आप अपने प्रोग्राम को क्रैश करने वाले संकेतों को पकड़ सकते हैं और QSharedMemory विनाशक को कॉल करने वाले हैंडलर का उपयोग कर सकते हैं।

+0

क्या मैं मैन्युअल रूप से एक विनाशक को कॉल कर सकता हूं – destan

+0

हां, उदा। कक्षा फू के ऑब्जेक्ट एफ के लिए: 'एफ। ~ फू();'। लेकिन आपको केवल उन परिस्थितियों में ऐसा करना चाहिए जहां भाषा स्वचालित रूप से विनाशक को भी नहीं बुलाएगी। – bames53

+0

हां, आप कर सकते हैं - लेकिन मुझे नहीं पता कि यह सिग्नल हैंडलर में क्यूटी से संबंधित किसी भी चीज़ पर निर्भर हो सकता है, क्योंकि ऐसे हैंडलर स्वयं निहित होना चाहिए और प्रोग्राम में किसी और चीज पर रिले नहीं होना चाहिए। –

1

सत्य यह है कि यदि आपके कार्यक्रम को मारने की जरूरत है या सीगफॉल्ट है, तो आप वास्तव में इसके बारे में कुछ भी नहीं कर सकते हैं। यूनिक्स/लिनक्स के तहत सब्सक्रिप्शन के एकल उदाहरण को सुनिश्चित करने के लिए साझा स्मृति सबसे अच्छी पसंद नहीं है। इसके बजाय सेमफोर का उपयोग करने का प्रयास करें, जैसे ही आपका एप्लिकेशन समाप्त हो जाता है, वे बंद हो रहे हैं।

संपादित करें:

sem_close

सभी के प्रलेखन से नामित संकेतबाहु स्वचालित रूप से प्रक्रिया समाप्ति पर बंद हो जाती हैं खोलें, या execve पर (2)।

मैं भी जोड़ना होगा कि एकल-ऐप्स contraint सुनिश्चित linux की तरह सिस्टम पर अजीब परिणाम हो सकता है - कल्पना किसी को एक्स सुरंग के साथ ssh के माध्यम से लॉग इन किया और अपने अनुप्रयोग शुरू करने की कोशिश - अगर किसी को पहले से ही यह उपयोग कर रहा है, ऐसा नहीं होगा प्रारंभ। यह बल्कि confisunig होगा। आप एप्लिकेशन डेवलपर हैं और यदि आपको प्रति-सिस्टम प्रति-उपयोगकर्ता या प्रति-एक्स-सत्र नाकाबंदी की आवश्यकता होती है तो आपको सबसे अच्छा पता होना चाहिए।

यदि आप प्रति-उपयोगकर्ता नाकाबंदी का उपयोग करना चाहते हैं, तो समाधान वर्तमान पिड युक्त उपयोगकर्ता होम निर्देशिका में छिपी हुई फ़ाइल को जोड़ना हो सकता है। अगला एप्लिकेशन इस फ़ाइल की जांच करेगा, और यदि यह मौजूद है और वर्तमान बाइनरी में/proc/[pid]/exe लिंक पॉइंट मौजूद है, तो त्रुटि लौटाएं।

+0

को बहिष्कृत किया गया है, लेकिन मुझे लगता है कि मुझे सिस्टम-व्यापी सेमफोर सही चाहिए? – destan

+0

नाम संकेतबाहु सटीक –

+0

होने के लिए लेकिन वहाँ एक ही समस्या, उत्पन्न होने पर दुर्घटनाग्रस्त हो गया सेमाफोर – destan

1

आप अपने सिस्टम पर साझा स्मृति, सेमफोर इत्यादि मैन्युअल रूप से साफ़ करने के लिए अपने प्रोग्राम को समाप्त करने के बाद हमेशा एक स्क्रिप्ट चला सकते हैं (मेरा मैक प्रो चल रहा है 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 
संबंधित मुद्दे