Ho un background Java e adoro usare il segnale QUIT per ispezionare il dump del thread Java.
Come lasciare che Golang stampi tutte le tracce dello stack di goroutine?
Ho un background Java e adoro usare il segnale QUIT per ispezionare il dump del thread Java.
Come lasciare che Golang stampi tutte le tracce dello stack di goroutine?
Risposte:
Per stampare la traccia dello stack per la goroutine corrente , utilizzare PrintStack()daruntime/debug .
PrintStack stampa sull'errore standard la traccia dello stack restituita da Stack.
Per esempio:
import(
"runtime/debug"
)
...
debug.PrintStack()
Per stampare la traccia dello stack per tutti i goroutine utilizzare Lookupe WriteToda 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.
Ogni profilo ha un nome univoco. Alcuni profili sono predefiniti:
goroutine - tracce dello stack di tutti gli
heap goroutine correnti - un campionamento di tutte le allocazioni di heap
threadcreate - tracce dello stack che hanno portato alla creazione di nuovi thread del sistema operativo
block - tracce dello stack che hanno portato al blocco delle primitive di sincronizzazione
Per esempio:
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
Stack. "Stack restituisce un'analisi dello stack formattata della goroutine che la chiama. Per ogni routine, include le informazioni sulla riga di origine e il valore del PC, quindi tenta di scoprire, per le funzioni Go, la funzione o il metodo chiamante e il testo della riga contenente invocazione."
C'è un frontend HTTP per il runtime/pprofpacchetto menzionato nella risposta di Intermernet. Importa il pacchetto net / http / pprof per registrare un gestore HTTP per /debug/pprof:
import _ "net/http/pprof"
import _ "net/http"
Avvia un listener HTTP se non ne hai già uno:
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
Quindi punta un browser su http://localhost:6060/debug/pprofper un menu o http://localhost:6060/debug/pprof/goroutine?debug=2per uno stack dump goroutine completo.
Ci sono anche altre cose divertenti che puoi imparare sul tuo codice in esecuzione in questo modo. Guarda il post del blog per esempi e maggiori dettagli: http://blog.golang.org/profiling-go-programs
Per imitare il comportamento Java di stack-dump su SIGQUIT ma lasciando il programma in esecuzione:
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])
}
}()
Simile a Java, SIGQUIT può essere utilizzato per stampare una traccia dello stack di un programma Go e le sue goroutine.
Una differenza fondamentale, tuttavia, è che per impostazione predefinita l'invio di SIGQUIT a programmi Java non li termina, mentre i programmi Go terminano.
Questo approccio non richiede modifiche al codice per stampare una traccia dello stack di tutte le goroutine dei programmi esistenti.
La variabile d'ambiente GOTRACEBACK ( vedere la documentazione del pacchetto runtime ) controlla la quantità di output generato. Ad esempio, per includere tutte le goroutine, imposta GOTRACEBACK = all.
La stampa dello stack trace è innescata da una condizione di runtime imprevista (segnale non gestito), originariamente documentata in questo commit , rendendola disponibile almeno a partire da Go 1.1.
In alternativa, se la modifica del codice sorgente è un'opzione, vedere altre risposte.
Notare che in un terminale Linux, SIGQUIT può essere comodamente inviato con la combinazione di tasti Ctrl+ \.
Puoi usare runtime.Stack per ottenere la traccia dello stack di tutte le goroutine:
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
fmt.Printf("%s", buf)
Dalla documentazione:
func Stack(buf []byte, all bool) int
Stack formatta una traccia dello stack della goroutine chiamante in buf e restituisce il numero di byte scritti in buf. Se tutto è vero, Stack formati impilano le tracce di tutte le altre goroutine in buf dopo la traccia per la goroutine corrente.
string(buf)qui fmt.Printf("%s", buf)e fmt.Printf("%s", string(buf))fare la stessa identica cosa (vedere la documentazione per il fmtpacchetto); l'unica differenza qui è che la stringversione copierà bufinutilmente i byte da
Premi CTRL + \
(Se lo esegui in un terminale e vuoi solo terminare il tuo programma e scaricare le routine go ecc.)
Ho trovato questa domanda cercando la sequenza di tasti. Volevo solo un modo semplice e veloce per sapere se il mio programma perdeva le routine di go :)
Sui sistemi * NIX (incluso OSX) invia un segnale di interruzione SIGABRT:
pkill -SIGABRT program_name
È necessario utilizzare la lunghezza restituita da runtime.Stack()per evitare di stampare un mucchio di righe vuote dopo la traccia dello stack. La seguente funzione di ripristino stampa una traccia ben formattata:
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]))
}
Per impostazione predefinita, premere i ^\tasti ( CTRL + \ ) per scaricare le tracce dello stack di tutte le goroutine.
Altrimenti, per un controllo più granulare, puoi usare panic. Il modo più semplice a partire da Go 1.6+ :
go func() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
Quindi, esegui il programma in questo modo:
# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go
Se vuoi anche stampare go runtime goroutine:
$ GOTRACEBACK=system go run main.go
Ecco tutte le opzioni di GOTRACEBACK:
GOTRACEBACK=none omette completamente le tracce dello stack goroutine.GOTRACEBACK=single (l'impostazione predefinita) si comporta come descritto sopra.GOTRACEBACK=all aggiunge tracce dello stack per tutte le goroutine create dall'utente.GOTRACEBACK=system è come "tutti" ma aggiunge stack frame per le funzioni di runtime e mostra le goroutine create internamente dal runtime.GOTRACEBACK=crashè come `` sistema '' ma si arresta in modo anomalo in un modo specifico del sistema operativo invece di uscire. Ad esempio, su sistemi Unix, il crash si verifica SIGABRTper attivare un core dump.La variabile GOTRACEBACK controlla la quantità di output generata quando un programma Go non riesce a causa di un panico non recuperato o di una condizione di runtime imprevista.
Per impostazione predefinita, un errore stampa una traccia dello stack per la goroutine corrente, eliminando le funzioni interne al sistema di runtime, quindi esce con il codice di uscita 2. L'errore stampa le tracce dello stack per tutte le goroutine se non c'è goroutine corrente o l'errore è interno al tempo di esecuzione.
Per ragioni storiche, le impostazioni GOTRACEBACK 0, 1 e 2 sono sinonimi rispettivamente di none, all e system.
La funzione SetTraceback del pacchetto runtime / debug consente di aumentare la quantità di output in fase di esecuzione, ma non può ridurre la quantità inferiore a quella specificata dalla variabile di ambiente. Vedi https://golang.org/pkg/runtime/debug/#SetTraceback .