2011-06-14 22 views
5

tl; डॉ: एक पर्ल httpd प्रक्रिया स्मृति से बाहर होने पर एक पर्ल स्टैक ट्रेस कैसे डंप करें।पर्ल से "स्मृति से बाहर" त्रुटि

हमारे पास एक mod_perl 2 सर्वर, पर्ल 5.8.8, आरएचईएल 5.6, लिनक्स 2.6.18 है।

बहुत ही कभी और अप्रत्याशित रूप से, एक बच्चा httpd प्रक्रिया सभी उपलब्ध स्मृति को खतरनाक दर पर उपयोग करना शुरू कर देती है। हमने कम से कम बीएसडी :: संसाधन :: setrlimit (RLIMIT_VMEM, ...) का उपयोग किया है, ताकि सर्वर को नीचे लाने से पहले प्रक्रिया "स्मृति से बाहर" हो जाए।

हम नहीं जानते कि यह कोड कहां हो रहा है, और लोड परीक्षण के घंटों के बिना पुन: पेश करना मुश्किल है।

क्या हम वास्तव में चाहते हैं एक तरह से एक पर्ल स्टैक ट्रेस बस से पहले प्रक्रिया स्मृति से बाहर चलाता है पाने के लिए है, इसलिए हम जानते हैं कि कोड इस खड़ी कर रहा है। दुर्भाग्य से, "स्मृति से बाहर" एक untrappable error है।

1) $^M emergency memory pool का उपयोग करें:

विकल्प यहां मैं विचार कर रहा हूँ, उनकी कमियां के साथ प्रत्येक रहे हैं। हमें PERD को पुन: संकलित करने की आवश्यकता है -DPERL_EMERGENCY_SBRK और -Dusemymalloc।

2) लॉग बयान में डाल दें, फिर यह देखने के लिए लॉग का विश्लेषण करें कि प्रक्रिया कहां बंद हो रही है।

3) एक बाहरी स्क्रिप्ट लिखें जो लगातार httpd प्रक्रियाओं के पूल को स्कैन करती है, और यदि यह बहुत सारी मेमोरी का उपयोग करके देखती है, तो इसे एक यूएसआर 2 सिग्नल भेजता है (जिसे हमने स्टैक ट्रेस डंप करने की व्यवस्था की है)।

4) किसी भी तरह की प्रक्रिया पर नजर रखने के लिए अपने स्वयं के स्मृति लगातार, और एक स्टैक ट्रेस डंप जब स्मृति उच्च लेकिन "मेमोरी से बाहर" त्रुटि से पहले हो जाता है की है।

धन्यवाद!

जॉन

+0

क्या [Devel :: NYTProf] (http://search.cpan.org/perldoc?Devel::NYTProf) के तहत प्रक्रिया को चलाने के लिए संभव है? –

+0

जैसा कि मैंने कहा था, समस्या बहुत ही कम होती है - चलो एक घंटे के लोड परीक्षण के बाद कहें - इसलिए अगर हम प्रोफाइलिंग के तहत या भारी लॉगिंग के तहत भाग गए तो हमें बड़ी मात्रा में डेटा एकत्र करना होगा। साथ ही यह अच्छा होगा समाधान जो उत्पादन में काम करेगा, जहां स्पष्ट रूप से हम डेवेल :: NYTProf के तहत नहीं चल सकते हैं। –

उत्तर

2

आप malloc/मुक्त के एक कस्टम संस्करण लोड करने के लिए LD_PRELOAD आज़मा सकते हैं। किसी भी चीज़ को फिर से जोड़ने या पुन: संकलित करना आवश्यक नहीं होना चाहिए। बस एक .so malloc रूप में एक ही इंटरफ़ेस है कि करने के लिए LD_PRELOAD सेट है, और malloc की इस प्रीलोडेड संस्करण सामान्य प्रणाली malloc के बजाय लोड किया जाएगा जब आप अपने निष्पादन चलाते हैं। उदाहरण के लिए, efence के साथ मेमोरी त्रुटियों का पता लगाने के लिए यह एक आम रणनीति है।

मुझे नहीं लगता कि efence यहाँ आप के लिए काम करेंगे के रूप में है कि स्मृति का पता लगाने अधिलेखित कर देता है, स्मृति से बाहर डिबगिंग नहीं (मैं नहीं जानता कि क्या यह OOM पर करता है) के लिए है। मुझे लगता है कि आप failmalloc को देखना चाहते हैं। मैं इस एक इस्तेमाल कभी नहीं किया है, लेकिन जैसे कि यह तुम क्या चाहते (मैं केवल पहले पन्ने स्किम्ड) कर सकते हैं यह लग रहा है।

+0

दिलचस्प। तो सैद्धांतिक रूप से मैं एक मॉलोक हुक (http://www.gnu.org/s/hello/manual/libc/Hooks-for-Malloc.html) बना सकता हूं जो मॉलोक को कॉल करता है, और यदि ओओएम होता है, 1) उठाएं मुलायम VMEM सीमा 2) एक ही तर्क (जो अब उच्च सीमा के साथ सफल होना चाहिए) 3) के साथ फिर से कॉल malloc (एक पर्ल स्टैक ट्रेस डंप करने के लिए प्रक्रिया अपने आप में एक SIGUSR2) –

3

आप mod_backtrace के साथ एक पश्व-अनुरेखन मिलता है, Andy Millar's introduction देख सकते हैं। पश्व-अनुरेखन सी स्तर पर है, आप या तो की जरूरत है ताकि

  • पर्ल का एक सा ज्ञान internals अनुमान लगाने के लिए पर्ल बस पश्व-अनुरेखन या
  • gdb को चलाने के लिए को देखकर ढेर, crashy समारोह में एक ब्रेकपाइंट सेट और mod_perl पुस्तक से gdb मैक्रोज़ के साथ पर्ल स्टैक और लेक्सिकल वेरिएबल्स की जांच करें।
+0

धन्यवाद भेजकर जैसे मिलता है। क्या सी-लेवल बैकट्रैस में वास्तव में पर्याप्त जानकारी है यह निर्धारित करने के लिए कि हम पर्ल स्टैक में कहां हैं, न सिर्फ कोड की लाइन बल्कि कॉलर्स इत्यादि। –

+0

जोनाथन: कहीं, कहीं है, लेकिन यह जरूरी नहीं है कि यह आसान या सार्वजनिक हो। आप कार्लो :: वापस करने के लिए पर्ल में कॉल करने के लिए call_sv/etc (perlcall देखें) का उपयोग कर सकते हैं। आपकी स्मृति बाधाओं को पकड़ने के लिए अनुमति दें। – tsee

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