2011-01-22 17 views
5

मुझे पता है कि मैं बैकट्रैस() या [एनएसटीएचड कॉलस्टैकसिंबल्स] का उपयोग कर वर्तमान धागे का स्टैक ट्रेस प्राप्त कर सकता हूं, लेकिन मैं एक अलग धागे के स्टैक ट्रेस पर कैसे पहुंचूंगा (माना जाता है कि यह जमे हुए है)?किसी अन्य धागे से एक स्टैक ट्रेस प्रिंट करना

उत्तर

10

संपादित करें: मेरा मूल उत्तर मनमाने ढंग से धागे से प्रिंट नहीं होगा। मैं के बाद से मेरी दुर्घटना हैंडलर परियोजना में एक उचित कार्यान्वयन लिखा है: https://github.com/kstenerud/KSCrash

विशेष रूप से, इन फ़ाइलों:

से कुछ मदद के साथ:

तुम क्या है:

  • एक नई मशीन संदर्भ संरचना (_STRUCT_MCONTEXT)
  • thread_get_state का उपयोग कर अपने ढेर राज्य में भरें बनाओ()
  • कार्यक्रम काउंटर जाओ (पहला स्टैक ट्रेस एंट्री) और फ्रेम पॉइंटर (बाकी सभी)
  • फ्रेम पॉइंटर द्वारा इंगित स्टैक फ्रेम के माध्यम से चरण और सभी निर्देशों को स्टोर करें बाद में उपयोग के लिए एक बफर में ddresses।

ध्यान दें कि आपको ऐसा करने से पहले धागे को रोकना चाहिए या अन्यथा आप अप्रत्याशित परिणाम प्राप्त कर सकते हैं।

स्टैक फ्रेम संरचनाओं दो संकेत युक्त से भर जाता है: स्टैक पर अगले स्तर तक के

  • सूचक
  • अनुदेश पता

तो आपको लगता है कि लेने के लिए खाते जब में की जरूरत है अपने स्टैक ट्रेस को भरने के लिए फ्रेम चलना। एक दूषित ढेर की भी संभावना है, जिससे एक खराब सूचक होता है, जो आपके कार्यक्रम को दुर्घटनाग्रस्त कर देगा। आप vm_read_overwrite() का उपयोग कर स्मृति की प्रतिलिपि बनाकर इसे प्राप्त कर सकते हैं, जो पहले कर्नेल से पूछता है कि अगर इसमें स्मृति तक पहुंच है, तो यह क्रैश नहीं होता है।

एक बार आपके पास स्टैक ट्रेस होने के बाद, आप सामान्य पर बैकट्रैस() को कॉल कर सकते हैं (क्रैश हैंडलर को एसिंक-सुरक्षित होना चाहिए, इसलिए यह अपनी बैकट्रैक विधि लागू करता है, लेकिन सामान्य मामलों में बैकट्रैक() ठीक है) ।

+0

ध्यान दें कि जब आप अपना स्टैक पढ़ रहे हों तो आपको थ्रेड को निलंबित करना चाहिए। – Albert

+0

इसके अलावा, क्या आप वाकई यह काम करते हैं? यह '__builtin_frame_address' का उपयोग करता है जो हमेशा ** वर्तमान ** थ्रेड के बारे में होता है। – Albert

+0

तो यह पता चला है कि यह वास्तव में काम नहीं करता है (यह एक स्टैक ट्रेस प्रिंट करता है, लेकिन मुझे नहीं पता था कि यह वर्तमान धागे से प्रिंट कर रहा था)। मेरे पास कुछ नया कोड है जो इरादे से काम करता है, लेकिन यह अभी तक रिलीज के लिए तैयार नहीं है। एक बार तैयार होने के बाद मैं एक अद्यतन पोस्ट करूंगा। – Karl

3

कॉलस्टैक को किसी अन्य थ्रेड से प्राप्त करने का कुछ सुरक्षित तरीका यहां दिया गया है: Implementation और some background information। यह सिग्नल हैंडलिंग का उपयोग करता है और लक्ष्य थ्रेड में सिग्नल हैंडलर स्पॉन्स करता है। यह भी लाभ है कि यह आपके समाधान की तुलना में अधिक क्रॉस-प्लेटफॉर्म है, यानी इसे कहीं भी काम करना चाहिए जहां आपके पास <signal.h> और <execinfo.h> है।

प्रिंटिंग के लिए, आप backtrace_symbols का उपयोग अपने स्वयं के सुझाव में कर सकते हैं। लेकिन आप इसे here लागू किए गए विस्तारित संस्करण में रुचि रखते हैं।यह libbfd का उपयोग करता है (binutils से; हालिया संस्करण मैकॉक्स पर भी काम करता है, here को एक छोटी सी सीमा के लिए देखें जो आपके लिए प्रासंगिक नहीं हो सकता है) डीबगिंग जानकारी पढ़ने और लाइन-नंबर और अन्य जानकारी जोड़ने के लिए (यह भी वापस आ जाता है dladdr यदि सब कुछ विफल हो जाता है, तो backtrace_symbols क्या कर रहा है)।

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