गोरोइनिन स्टैकट्रैक्स डंप कैसे करें?


91

मेरे पास जावा बैकग्राउंड है, और मुझे जावा थ्रेड डंप का निरीक्षण करने के लिए सिग्नल QUIT का उपयोग करना पसंद है।

गोलंग को सभी गोरोइन्ट्स स्टैक ट्रेस को कैसे जाने दें?


क्या इससे आपके सवाल का जवाब मिलता है? कैसे एक आतंक का
ढेर

जवाबों:


107

के लिए स्टैक ट्रेस मुद्रित करने के लिए वर्तमान goroutine, का उपयोग PrintStack()सेruntime/debug

PrintStack मानक त्रुटि के लिए प्रिंट करता है स्टैक द्वारा लौटाए गए स्टैक ट्रेस।

उदाहरण के लिए:

import(
   "runtime/debug"
)
...    
debug.PrintStack()

सभी goroutines के उपयोग Lookupऔर WriteToसे स्टैक ट्रेस प्रिंट करने के लिए runtime/pprof

func Lookup(name string) *Profile
// Lookup returns the profile with the given name,
// or nil if no such profile exists.

func (p *Profile) WriteTo(w io.Writer, debug int) error
// WriteTo writes a pprof-formatted snapshot of the profile to w.
// If a write to w returns an error, WriteTo returns that error.
// Otherwise, WriteTo returns nil.

प्रत्येक प्रोफ़ाइल का एक अद्वितीय नाम है। कुछ प्रोफाइल पूर्वनिर्धारित हैं:

goroutine - सभी वर्तमान goroutines
ढेर के
ढेर के निशान - सभी ढेर आवंटन का एक नमूना थ्रेडक्रिएट - स्टैक के निशान जिसके कारण नए OS थ्रेड
ब्लॉक का निर्माण हुआ - स्टैक के निशान जिसके कारण सिंक्रोनस प्राइमेटीज पर अवरुद्ध हो गया।

उदाहरण के लिए:

pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)

1
क्या यह सभी गोरआउट्स के स्टैक ट्रेस को प्रिंट करता है?

यह चाहिए, यह कहता है Stack। "स्टैक गोरोइन का एक स्वरूपित स्टैक ट्रेस देता है जो इसे कॉल करता है। प्रत्येक दिनचर्या के लिए, इसमें स्रोत लाइन की जानकारी और पीसी मूल्य शामिल है, फिर गो फ़ंक्शन, कॉलिंग फ़ंक्शन या विधि और लाइन वाले पाठ के लिए खोज करने का प्रयास करता है। मंगलाचरण।"
इंटरमरनेट

1
क्षमा करें, यह केवल वर्तमान गोरआउट स्टैक ट्रेस को प्रिंट करता है।

4
@HowardGuo मैंने सभी स्टैक ट्रैस को डंप करने के लिए रनटाइम / पीच का उपयोग करके एक उदाहरण जोड़ा है।
इंटरमरनेट

1
मुझे लगता है कि यह केवल प्रत्येक थ्रेड के वर्तमान में चल रहे गोरोइन का उत्पादन करता है, सभी गोरोइनों का नहीं , उदा: play.golang.org/p/0hVB0_LMdm
rogerdpack

39

runtime/pprofइंटरमेरनेट के उत्तर में उल्लिखित पैकेज के लिए एक HTTP फ्रंटएंड है । के लिए HTTP हैंडलर रजिस्टर करने के लिए नेट / http / pprof पैकेज आयात करें /debug/pprof:

import _ "net/http/pprof"
import _ "net/http"

यदि आपके पास पहले से कोई नहीं है, तो एक HTTP श्रोता शुरू करें:

go func() {
    log.Println(http.ListenAndServe("localhost:6060", nil))
}()

फिर http://localhost:6060/debug/pprofएक मेनू के http://localhost:6060/debug/pprof/goroutine?debug=2लिए या पूर्ण गोरोइन स्टैक डंप के लिए एक ब्राउज़र इंगित करें ।

अन्य मजेदार चीजें हैं जो आप अपने रनिंग कोड के बारे में भी सीख सकते हैं। उदाहरण और अधिक जानकारी के लिए ब्लॉग पोस्ट देखें: http://blog.golang.org/profiling-go-programs


मैं इसे इसके द्वारा चलाया गया केवल गोरोनाइट्स दिखाता है जहाँ तक मैं देखता हूँ। क्या कोई ऐसा तरीका है जिसे मैं सभी "तरीकों" को देख सकता हूं जो कि मुख्य.गो लॉन्च के बाद निष्पादित किए जाते हैं?
लुकास लुकाक

38

SIGQUIT पर स्टैक-डंप के जावा व्यवहार की नक़ल करना

go func() {
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGQUIT)
    buf := make([]byte, 1<<20)
    for {
        <-sigs
        stacklen := runtime.Stack(buf, true)
        log.Printf("=== received SIGQUIT ===\n*** goroutine dump...\n%s\n*** end\n", buf[:stacklen])
    }
}()

4
मुझे लगता है कि यह वही है जो लेखक वास्तव में देख रहा था- जावा क्या करता है जब आप एक मार-प्रेषण भेजते हैं। एक छोटा सा बदलाव जो मुझे करना था वह था () लूप की: (<- sigs) के लिए पहली पंक्ति को बदलना। दूसरे शब्दों में, बस उस पर इंतजार करने के बाद संकेत को छोड़ दें। गो के हाल के संस्करण आपको बाद में इसका उपयोग किए बिना एक चर घोषित नहीं करने देंगे।
जॉर्ज आर्महोल्ड

@Bryan, क्या आप इसे BSD या अन्य अधिक-अनुमेय शर्तों के तहत लाइसेंस देने के लिए तैयार हैं जो StackOverflow द्वारा आवश्यक CC-BY-SA 3.0 के लिए अतिरिक्त है?
चार्ल्स डफी

1
@CharlesDuffy आप अपाचे लाइसेंस के तहत यहां बहुत कुछ पा सकते हैं: github.com/weaveworks/weave/blob/…
ब्रायन

37

जावा के समान, SIGQUIT का उपयोग एक गो कार्यक्रम और इसके गोरआउट्स के स्टैक ट्रेस को प्रिंट करने के लिए किया जा सकता है।
हालाँकि, एक प्रमुख अंतर यह है कि डिफ़ॉल्ट रूप से जावा प्रोग्राम को SIGQUIT भेजना उन्हें समाप्त नहीं करता है, जबकि Go प्रोग्राम बाहर निकलते हैं।

इस दृष्टिकोण को मौजूदा कार्यक्रमों के सभी गोरआउट्स के स्टैक ट्रेस को मुद्रित करने के लिए कोई कोड परिवर्तन की आवश्यकता नहीं है।

पर्यावरण चर GOTRACEBACK ( रनटाइम पैकेज के प्रलेखन देखें) ) उत्पन्न उत्पादन की मात्रा को नियंत्रित करता है। उदाहरण के लिए, सभी गोरआउट्स को शामिल करने के लिए, GOTRACEBACK = सभी सेट करें।

स्टैक ट्रेस की छपाई को एक अनपेक्षित रनटाइम कंडीशन (अनहेल्ड सिग्नल) द्वारा ट्रिगर किया जाता है, मूल रूप से इस कमिट में प्रलेखित है , जो कम से कम गो 1.1 के बाद से उपलब्ध है।


वैकल्पिक रूप से, यदि स्रोत कोड को संशोधित करना एक विकल्प है, तो अन्य उत्तर देखें।


ध्यान दें कि लिनक्स टर्मिनल में, SIGQUIT को आसानी से कुंजी संयोजन Ctrl+ के साथ भेजा जा सकता है \


5
डॉक्स के माध्यम से देखने के दौरान मुझे SIGQUIT का कोई उल्लेख नहीं मिला, बल्कि SIGABRT का। अपने स्वयं के परीक्षणों (1.7 के साथ) से बाद वाले ने भी पूर्व में काम किया।
सॉलिटश

4
यह शीर्ष उत्तर होना चाहिए।
स्टीवन सोरोका

डॉक्स "जब एक अपरिचित आतंक या एक अप्रत्याशित रनटाइम स्थिति के कारण एक गो कार्यक्रम विफल हो जाता है" को संदर्भित करता है। एक अनकहा संकेत (SIGQUIT, आदि) उत्तरार्द्ध में से एक है। मैंने SIGQUIT का उल्लेख क्यों किया? क्योंकि ओपी जावा के साथ SIGQUIT का उपयोग करने के लिए अपने प्यार को व्यक्त करता है, और यह जवाब समानता पर जोर देता है। इसे स्पष्ट करने के लिए उत्तर को रिकॉर्ड करना।
रोडोल्फो कार्वाल्हो

26

आप सभी goroutines के स्टैक ट्रेस पाने के लिए runtime.Stack का उपयोग कर सकते हैं :

buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
fmt.Printf("%s", buf)

प्रलेखन से:

func Stack(buf []byte, all bool) int

स्टैक, कॉलिंग गोरोइन के एक स्टैक को buf में प्रारूपित करता है और buf को लिखे गए बाइट्स की संख्या लौटाता है। यदि सब सही है, तो स्टैक प्रारूप वर्तमान गोरोइन के लिए ट्रेस के बाद अन्य सभी गोरोइनों के निशान को बफ़ में जोड़ देता है।


यह सभी गोरोइन्ट्स से backtraces , अच्छा शामिल है!
रोजगारपैक

क्या यह वह प्रारूप है जिसका उपयोग करने के लिए एक अपरिचित आतंक उबलता है?
Ztyx

2
स्ट्रिंग (buf) जोड़ना न भूलें या आप वहां कच्ची बाइट्स प्रिंट करेंगे।
कोड़ा

2
शायद मैं कुछ गलत कर रहा हूं, या शायद कार्यक्षमता बदल गई है, लेकिन यह मेरे लिए बाइट्स के एक खाली स्लाइस के अलावा कुछ भी पुनर्प्राप्त नहीं करता है?
17xande

1
@ कोडा को string(buf)यहां करने की आवश्यकता नहीं है, fmt.Printf("%s", buf)और fmt.Printf("%s", string(buf))ठीक उसी काम को करें ( fmtपैकेज के लिए डॉक्स देखें ); यहाँ केवल अंतर यह है कि stringसंस्करण bufअनावश्यक रूप से बाइट्स की नकल करेगा
kbolino

20

प्रेस Ctrl + \

(यदि आप इसे एक टर्मिनल में चलाते हैं और सिर्फ अपने प्रोग्राम को मारना चाहते हैं और गो रूट आदि को डंप करते हैं)

मुझे यह प्रश्न प्रमुख अनुक्रम की तलाश में मिला। बस एक त्वरित और आसान तरीका बताना चाहता था कि क्या मेरा कार्यक्रम लीक हो रहा है :)


11

पर * NIX सिस्टम (OSX सहित) एक संकेत गर्भपात भेजें SIGABRT:

pkill -SIGABRT program_name


जाहिरा तौर पर, SIGQUIT को एक जावा प्रक्रिया में भेजना इसे SIGABRT की तरह समाप्त नहीं करेगा।
डेव सी

मैंने इसे मूल प्रश्न का सबसे सरल और सबसे अधिक मिलान वाला समाधान पाया। अक्सर आपको अपना कोड बदले बिना, तुरंत एक स्टैकट्रेस की आवश्यकता होती है।
jotrocken

5

runtime.Stack()आपके स्टैक ट्रेस के बाद खाली लाइनों के एक गुच्छा को प्रिंट करने से बचने के लिए लौटे लंबाई का उपयोग करना आवश्यक है । निम्न पुनर्प्राप्ति फ़ंक्शन एक अच्छी तरह से स्वरूपित ट्रेस प्रिंट करता है:

if r := recover(); r != nil {
    log.Printf("Internal error: %v", r))
    buf := make([]byte, 1<<16)
    stackSize := runtime.Stack(buf, true)
    log.Printf("%s\n", string(buf[0:stackSize]))
}


मैंने ऐसा कभी नहीं देखा; आप किस प्लेटफार्म पर चल रहे हैं?
ब्रायन

ऐसा क्या है जो आपने नहीं देखा है? कोड सभी प्लेटफार्मों पर चलना चाहिए; मैंने इसे विंडोज 7, उबंटू 14.04 और मैक पर टेस्ट किया है।
डेविड टोटिल

कभी खाली लाइनें नहीं देखीं।
ब्रायन

4

डिफ़ॉल्ट रूप से, सभी गोरआउट्स के स्टैक के निशान को डंप करने के लिए ^\( CTRL + \ ) दबाएँ


अन्यथा, अधिक दानेदार नियंत्रण के लिए, आप उपयोग कर सकते हैं panicगो 1.6+ का सरल तरीका :

go func() {
    s := make(chan os.Signal, 1)
    signal.Notify(s, syscall.SIGQUIT)
    <-s
    panic("give me the stack")
}()

फिर, अपना प्रोग्राम ऐसे चलाएं:

# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go

अगर आप भी गो रनटाइम गोरोइन प्रिंट करना चाहते हैं:

$ GOTRACEBACK=system go run main.go

यहां सभी GOTRACEBACK विकल्प दिए गए हैं:

  • GOTRACEBACK=none गोरोइन स्टैक के निशान को पूरी तरह से छोड़ देता है।
  • GOTRACEBACK=single (डिफ़ॉल्ट) ऊपर वर्णित अनुसार व्यवहार करता है।
  • GOTRACEBACK=all सभी उपयोगकर्ता-निर्मित गोरआउट के लिए स्टैक के निशान जोड़ता है।
  • GOTRACEBACK=system `` 'की तरह है, लेकिन रन-टाइम फ़ंक्शंस के लिए स्टैक फ़्रेम जोड़ता है और रन-टाइम द्वारा आंतरिक रूप से बनाए गए गोरआउट्स दिखाता है।
  • GOTRACEBACK=crash`` सिस्टम 'की तरह है, लेकिन बाहर निकलने के बजाय एक ऑपरेटिंग सिस्टम-विशिष्ट तरीके से क्रैश होता है। उदाहरण के लिए, यूनिक्स प्रणालियों पर, क्रैश SIGABRTएक कोर डंप को ट्रिगर करने के लिए उठता है।

यहाँ प्रलेखन है

GOTRACEBACK वैरिएबल उत्पादन की मात्रा को नियंत्रित करता है जब एक अपरिवर्तित आतंक या अप्रत्याशित रनटाइम स्थिति के कारण एक गो कार्यक्रम विफल हो जाता है।

डिफ़ॉल्ट रूप से, एक विफलता वर्तमान गोरोइन के लिए एक स्टैक ट्रेस को प्रिंट करती है, रन-टाइम सिस्टम के लिए आंतरिक कार्यों को पूरा करती है, और फिर बाहर निकलने के कोड के साथ बाहर निकलती है। विफलता वर्तमान गोरोइन या विफलता नहीं होने पर सभी गोरआउट के लिए स्टैक का निशान लगाती है। रन-टाइम को आंतरिक।

ऐतिहासिक कारणों से, GOTRACEBACK सेटिंग्स 0, 1, और 2 क्रमशः, सभी और सिस्टम के लिए समानार्थक हैं।

रनटाइम / डीबग पैकेज का सेटट्रेसबैक फ़ंक्शन रन टाइम पर आउटपुट की मात्रा बढ़ाने की अनुमति देता है, लेकिन यह पर्यावरण चर द्वारा निर्दिष्ट राशि को कम नहीं कर सकता है। Https://golang.org/pkg/runtime/debug/#SetTraceback देखें ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.