2009-05-18 19 views
25

मुझे एक लाइब्रेरी फ़ंक्शन कॉल करने की आवश्यकता है जो दुर्भाग्य से किसी दिए गए समय के भीतर कभी-कभी समाप्त नहीं होगी। क्या फ़ंक्शन को कॉल करने का कोई तरीका है लेकिन अगर इसे n सेकेंड के भीतर समाप्त नहीं किया जाता है तो इसे निरस्त करें?सी ++: मनमानी फ़ंक्शन कॉल के लिए टाइमआउट कैसे कार्यान्वित करें?

मैं फ़ंक्शन को संशोधित नहीं कर सकता, इसलिए मैं इसे निरस्त स्थिति में सीधे नहीं डाल सकता। मुझे को फ़ंक्शन में टाइमआउट जोड़ें।

क्या यह संभवतः एक (बूस्ट) थ्रेड के रूप में शुरू करने का एक संभावित समाधान है, जिसे मैं निश्चित समय के बाद समाप्त कर सकता हूं? क्या ऐसा कुछ काम करेगा? मुझे वास्तव में विश्वास है कि फ़ंक्शन थ्रेड-सुरक्षित नहीं है, लेकिन इससे कोई फर्क नहीं पड़ता कि मैं इसे केवल सिंगल थ्रेड के रूप में चलाता हूं, है ना? क्या अन्य (बेहतर) समाधान हैं?

+0

लाइब्रेरी फ़ंक्शन क्या करता है? – peterchen

+0

उह, कुछ गणना करें ... एक वैज्ञानिक गणना जो वास्तव में कुछ शर्तों के तहत समाप्त नहीं होगी। – Frank

उत्तर

18

आप एक boost::thread अंडे एपीआई कॉल करने के लिए कर सकते हैं:

boost::thread api_caller(::api_function, arg1, arg2); 
if (api_caller.timed_join(boost::posix_time::milliseconds(500))) 
{ 
    // API call returned within 500ms 
} 
else 
{ 
    // API call timed out 
} 

बूस्ट आप कार्यकर्ता धागा, हालांकि मारने के लिए अनुमति नहीं है। इस उदाहरण में, यह सिर्फ अनाथ है।

आपको एपीआई कॉल के बारे में सावधान रहना होगा, क्योंकि यह कभी भी संसाधनों को प्राप्त नहीं कर सकता है।

+1

यदि api_function एक मान देता है, तो मैं इसे कैसे एक्सेस कर सकता हूं? –

+0

यह विधि एक साधारण मजेदार बनाता है जो सीधे एपीआई को कॉल करता है। नतीजे को कैप्चर करने के लिए, आपको एपीआई के रिटर्न कोड को कुछ वैरिएबल को असाइन करने के लिए अपना खुद का फ़ैक्टर या लैम्ब्डा लिखना होगा जिसे कहीं और से एक्सेस किया जा सकता है। सी ++ 0x में, आप 'RETTYPE रीकोड लिख सकते हैं; boost :: thread api_caller ([& retcode] (टाइप 1 arg1, type2 arg2) {retcode = :: api_function (arg1, arg2);}); ' –

8

आप किस बारे में बात कर रहे हैं उसे आम तौर पर "वॉचडॉग" सिस्टम कहा जाता है। वॉचडॉग आमतौर पर एक दूसरा थ्रेड होता है जो अन्य सभी धागे की स्थिति पर जांच करता है। वॉचडॉग आमतौर पर समय-समय पर चलाने के लिए सेटअप होता है। यदि अन्य धागे से कोई प्रतिक्रिया प्राप्त नहीं हुई है, तो वॉचडॉग उपयोगकर्ता को सूचित कर सकता है, या अगर आप सुरक्षित रूप से ऐसा करना संभव हो तो अपमानजनक थ्रेड को भी मार सकते हैं (आपके आवेदन पर निर्भर करता है)।

+4

लाइब्रेरी फ़ंक्शन क्या कर रहा है, इस पर निर्भर करता है कि उत्तरदायी धागा को मारना बहुत असुरक्षित हो सकता है। कार्य को एक अलग प्रक्रिया में प्रेषित करने के लिए एक सुरक्षित दृष्टिकोण होगा। –

+0

मैं इस तरह की एक अलग प्रक्रिया कैसे शुरू करूं? क्या मेरा एप्लिकेशन फ़ाइल सिस्टम के माध्यम से बिना कुछ डेटा (और कुछ परिणाम डेटा वापस प्राप्त कर सकता है) पास कर सकता है? – Frank

+1

यह कुछ हद तक जटिल है, और प्लेटफ़ॉर्म-विशिष्ट - मुझे लगता है कि आसानी से एक अलग स्टैक ओवरफ्लो प्रश्न हो सकता है। प्रक्रियाओं के बीच डेटा पास करने के कई तरीके हैं। इसे आईपीसी (इंटर-प्रोसेस कम्युनिकेशन) कहा जाता है और यह मंच-विशिष्ट भी है। –

3

धागे के साथ समस्या यह है कि कुछ संसाधन आप थ्रेड समाप्ति के बाद मुक्त नहीं होंगे। यदि आप संसाधनों को प्राप्त नहीं करते हैं जिन्हें आपको रिलीज़ करना है तो थ्रेड के साथ जाएं।

+2

ध्यान दें कि ऐसे संसाधन हैं जिन्हें आपके नियंत्रण में नहीं लिया जा सकता है - आप कॉल कर सकते हैं एपीआई जो ताले हासिल करते हैं और इसी तरह, थ्रेड को समाप्त करने के परिणामस्वरूप उन ताले को अनाथ कर दिया जाएगा। – Michael

14

मुझे लगता है कि इसे पूरा करने का एकमात्र सुरक्षित तरीका अलग-अलग सैंडबॉक्स प्रक्रिया को उत्पन्न करना होगा जो लाइब्रेरी फ़ंक्शन को आपके एप्लिकेशन के प्रॉक्सी के रूप में कॉल करता है। आपको अपने एप्लिकेशन और प्रॉक्सी के बीच कुछ प्रकार के आईपीसी को लागू करने की आवश्यकता होगी। आईपीसी जवाब पढ़ने पर एक टाइमआउट लागू करना काफी मामूली है। यदि रीडआउट टाइमआउट के कारण विफल रहता है, तो आप अपने आवेदन के स्वास्थ्य को जोखिम के बिना सुरक्षित रूप से प्रॉक्सी को समाप्त कर सकते हैं।

1

आपको जो चाहिए वह एक थ्रेड और Future Object है जो फ़ंक्शन कॉल से परिणाम प्राप्त कर सकता है।

बढ़ावा देने के उदाहरण के लिए here देखें।

आपको समय समाप्ति के बाद भविष्य की जांच करनी होगी और यदि यह सेट नहीं है, तो तदनुसार कार्य करें।

+1

वायदा शांत और अक्सर उपयोगी होते हैं, लेकिन मुझे नहीं लगता कि वे समस्या हल करते हैं ओपी ने पूछा। वह ** काम करना बंद करना चाहता है ** यदि यह बहुत लंबा चलता है। –

+0

वैसे वह समय सीमा समाप्त होने पर थ्रेड को समाप्त करने का प्रयास कर सकता है, लेकिन यह असुरक्षित है जितने अन्य लोगों ने इंगित किया है। यदि फ़ंक्शन बाद में समाप्त हो रहा है (जब तक यह टूटा न हो) तो भविष्य उन्हें समय-समय पर अपना मुख्य कार्यक्रम जारी रखने की अनुमति देगा और केवल थ्रेड और भविष्य को अनदेखा कर देगा कि यह भविष्य में समाप्त होने में कभी-कभी होगा। – lothar

3

Boost.Test के execution_monitor आप क्या चाहते हैं करता है:

http://www.boost.org/doc/libs/1_39_0/libs/test/doc/html/execution-monitor/reference.html#boost.execution_monitor

+2

+1, दिलचस्प विचार। मैं देखता हूं कि टाइमआउट पैरामीटर अभी तक विंडोज के लिए काम नहीं करता है। साथ ही, फ़ंक्शन द्वारा उपयोग किए जाने वाले किसी भी संसाधन को अभी भी एक अनिश्चित स्थिति (कम से कम गैरकानूनी, और संभवतः एक अमान्य मध्यवर्ती स्थिति में) में छोड़ा जा रहा है, इसलिए अपने कार्य को एक से अधिक बार चलाने या किसी भी छूने के आधार पर चलाने का प्रयास न करें। –

+0

इस प्रश्न का एक अच्छा कामकाजी उदाहरण है: [यह एक] (http://stackoverflow.com/questions/13690654/how-do-i-use-boost-execution-monitor-to-make-sure-if-my- समारोह-मिल-लटका यह वाई) – asanguinetti

3

समस्या यह है कि एक में प्रक्रिया समाधान समारोह से समर्थन के बिना के साथ संभावित रूप से अमान्य राज्य के साथ पहुंचते हैं।

उदाहरण: जब आप स्मृति आवंटन करते समय थ्रेड को समाप्त करते हैं, तो आपकी प्रक्रिया ढेर दूषित हो सकती है।

तो आप कॉल को समाप्त कर सकते हैं, लेकिन फिर आपको प्रक्रिया को समाप्त करना होगा। कई मामलों में, विनाशकारी साइड इफेक्ट्स की संभावना कम होती है, लेकिन मैं उस पर अपनी गणना शर्त नहीं लगाऊंगा।

बेन स्ट्राउब सुझाव देता है कि आप केवल धागे को अनाथ कर सकते हैं: इसे सबसे कम प्राथमिकता पर रखें और इसे अनंतता के लिए चलाएं। यह निश्चित रूप से केवल एक सीमित समाधान है: यदि धागा ressources (संभावना) का उपभोग करता है, तो वे सिस्टम को धीमा कर देंगे, प्रति प्रक्रिया धागे पर एक सीमा भी है (आमतौर पर थ्रेड स्टैक के लिए पता स्थान के कारण)।

आम तौर पर, मैं बाहरी प्रक्रिया समाधान पसंद करूंगा। एक साधारण पैटर्न यह है:
फ़ाइल में इनपुट डेटा लिखें, फ़ाइल के साथ बाह्य प्रक्रिया को तर्क के रूप में प्रारंभ करें। बाहरी प्रक्रिया एक डिस्क फ़ाइल में प्रगति (यदि कोई है) लिखती है जिस पर निगरानी की जा सकती है, और यह प्रक्रिया शुरू होने से प्रक्रिया को फिर से शुरू करने की अनुमति भी दे सकती है। परिणाम डिस्क पर लिखे गए हैं, और माता-पिता प्रक्रिया उन्हें पढ़ सकते हैं।

जब आप प्रक्रिया को समाप्त करते हैं, तो आपको अभी भी बाहरी संसाधनों (फ़ाइलों की तरह) तक पहुंच सिंक्रनाइज़ करना होगा, और छोड़े गए म्यूटिस से निपटने के लिए कैसे करें लिखित फाइलें आदि। लेकिन आमतौर पर यह एक मजबूत समाधान का तरीका है।

1

अनाथ प्रक्रिया के साथ जाएं, इसे लॉन्च करें और इसका निष्पादन समय दें। यदि यह समय से बाहर हो जाता है, तो इसे मारने के लिए ओएस का आह्वान करें।

रेस conds से कैसे बचें। इस पैटर्न पर:

  • आर्ग में स्टोर करने के लिए एक फ़ाइल (जाहिर है, सब कुछ Vals के रूप में पारित हो जाता है) पैदा करते हैं। अनाथ प्रक्रिया केवल इस फ़ाइल से डेटा पढ़ने की अनुमति है।

  • अनाथ इनपुट डेटा को संसाधित करता है, परिणाम मानों के साथ एक आउटपुट फ़ाइल बनाता है और इसे बंद कर देता है।

  • केवल जब सबकुछ किया जाता है, अनाथ इनपुट फ़ाइल को हटा देता है, एक तथ्य यह है कि काम करने वाली मास्टर प्रक्रिया को सिग्नल किया जाता है।

यह आधा लिखा फ़ाइलों समस्या पढ़ने से बचा जाता है, इनपुट फ़ाइल के अभाव मास्टर पहले नोटिस के बाद से, आउटपुट फ़ाइल है, जो निश्चित रूप से पूरा हो गया है पढ़ने के लिए खुलता है (क्योंकि इनपुट को हटाने से पहले बंद हो गया है, और ओएस कॉल के ढेर अनुक्रमिक हैं)।

1

"मुझे लाइब्रेरी फ़ंक्शन को कॉल करने की आवश्यकता है जो कभी-कभी किसी दिए गए समय के भीतर समाप्त नहीं होगा। दुर्भाग्यवश, क्या फ़ंक्शन को कॉल करने का कोई तरीका है, लेकिन अगर यह n सेकंड के भीतर समाप्त नहीं होता है तो इसे रोक दें?"

संक्षिप्त उत्तर नहीं है। यह आमतौर पर परेशानी होती है ... कॉल को स्वयं को कुछ समय पर समाप्त करना होगा (अपने स्वयं के टाइमआउट को कार्यान्वित करना), लेकिन कॉल अवरुद्ध करना आमतौर पर परेशानी होती है (उदा। Gethostbyname()) क्योंकि तब यह उनके (या सिस्टम) टाइमआउट पर निर्भर करता है, न कि आपके।

तो, जब भी संभव हो तो थ्रेड निकास में आवश्यक कोड को साफ़ करने की कोशिश करें - कोड को स्वयं को पहचानने और त्रुटि को संभालना चाहिए। यह एक संदेश और/या सेट स्टेटस भेज सकता है ताकि मुख्य (या अन्य) धागा जानता है कि क्या चल रहा है।

अत्यधिक प्राथमिक प्रणालियों में व्यक्तिगत प्राथमिकता, मुझे अपने थ्रेड कताई (हालांकि कोई व्यस्त-लॉकिंग नहीं) विशिष्ट टाइमआउट के साथ, गैर-अवरुद्ध कार्यों को कॉल करने और जगह पर सटीक निकास की स्थिति के साथ पसंद है। एक ग्लोबल या थ्रेड-विशिष्ट 'किया' चर एक साफ निकास के लिए चाल करता है।

संबंधित मुद्दे