J'ai une expérience en Java et j'aime utiliser le signal QUIT pour inspecter le vidage de thread Java.
Comment laisser Golang imprimer toutes les traces de la pile de goroutines?
J'ai une expérience en Java et j'aime utiliser le signal QUIT pour inspecter le vidage de thread Java.
Comment laisser Golang imprimer toutes les traces de la pile de goroutines?
Réponses:
Pour imprimer la trace de pile de la goroutine actuelle , utilisez PrintStack()
fromruntime/debug
.
PrintStack imprime en erreur standard la trace de pile renvoyée par Stack.
Par exemple:
import(
"runtime/debug"
)
...
debug.PrintStack()
Pour imprimer la trace de pile pour toutes les goroutines, utilisez Lookup
et à WriteTo
partir de 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.
Chaque profil a un nom unique. Quelques profils sont prédéfinis:
goroutine - traces de pile de tous les
tas de goroutines actuels - un échantillon de toutes les allocations de tas
threadcreate - traces de pile qui ont conduit à la création d'un nouveau
bloc de threads du système d'exploitation - traces de pile qui ont conduit au blocage des primitives de synchronisation
Par exemple:
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
Stack
. "Stack renvoie une trace de pile formatée de la goroutine qui l'appelle. Pour chaque routine, elle inclut les informations de la ligne source et la valeur PC, puis tente de découvrir, pour les fonctions Go, la fonction ou méthode appelante et le texte de la ligne contenant le invocation."
Il existe une interface HTTP pour le runtime/pprof
paquet mentionné dans la réponse d'Intermernet. Importez le package net / http / pprof pour enregistrer un gestionnaire HTTP pour /debug/pprof
:
import _ "net/http/pprof"
import _ "net/http"
Démarrez un écouteur HTTP si vous n'en avez pas déjà:
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
Puis pointez un navigateur vers http://localhost:6060/debug/pprof
pour un menu, ou http://localhost:6060/debug/pprof/goroutine?debug=2
pour un vidage complet de la pile de goroutine.
Vous pouvez également apprendre d'autres choses amusantes sur votre code en cours d'exécution. Consultez l'article de blog pour des exemples et plus de détails: http://blog.golang.org/profiling-go-programs
Pour imiter le comportement Java du stack-dump sur SIGQUIT tout en laissant le programme en cours d'exécution:
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])
}
}()
Semblable à Java, SIGQUIT peut être utilisé pour imprimer une trace de pile d'un programme Go et de ses goroutines.
Une différence clé, cependant, est que par défaut l'envoi de SIGQUIT aux programmes Java ne les termine pas, tandis que les programmes Go se terminent.
Cette approche ne nécessite aucun changement de code pour imprimer une trace de pile de toutes les goroutines des programmes existants.
La variable d'environnement GOTRACEBACK ( voir la documentation du package d'exécution ) contrôle la quantité de sortie générée. Par exemple, pour inclure toutes les goroutines, définissez GOTRACEBACK = all.
L'impression de la trace de la pile est déclenchée par une condition d'exécution inattendue (signal non géré), documentée à l'origine dans ce commit , la rendant disponible depuis au moins Go 1.1.
Sinon, si la modification du code source est une option, voir les autres réponses.
Notez que dans un terminal Linux, SIGQUIT peut être envoyé avec la combinaison de touches Ctrl+ \.
Vous pouvez utiliser runtime.Stack pour obtenir la trace de la pile de toutes les goroutines:
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
fmt.Printf("%s", buf)
De la documentation:
func Stack(buf []byte, all bool) int
Stack formate une trace de pile de la goroutine appelante en buf et renvoie le nombre d'octets écrits dans buf. Si tout est vrai, Stack formate les traces de toutes les autres goroutines dans buf après la trace de la goroutine actuelle.
string(buf)
ici, fmt.Printf("%s", buf)
et de fmt.Printf("%s", string(buf))
faire exactement la même chose (voir la documentation pour le fmt
paquet); la seule différence ici est que la string
version copiera les octets buf
inutilement
Appuyez sur CTRL + \
(Si vous l'exécutez dans un terminal et que vous voulez simplement tuer votre programme et vider les routines go, etc.)
J'ai trouvé cette question à la recherche de la séquence clé. Je voulais juste un moyen rapide et facile de savoir si mon programme fuit des routines go :)
Sur les systèmes * NIX (y compris OSX), envoyez un signal d'abandon SIGABRT
:
pkill -SIGABRT program_name
Il est nécessaire d'utiliser la longueur renvoyée par runtime.Stack()
pour éviter d'imprimer un tas de lignes vides après votre trace de pile. La fonction de récupération suivante imprime une trace joliment formatée:
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]))
}
Par défaut, appuyez sur les ^\
touches ( CTRL + \ ) pour vider les traces de pile de toutes les goroutines.
Sinon, pour un contrôle plus granulaire, vous pouvez utiliser panic
. Le moyen simple à partir de Go 1.6+ :
go func() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
Ensuite, exécutez votre programme comme ceci:
# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go
Si vous souhaitez également imprimer des goroutines d'exécution go:
$ GOTRACEBACK=system go run main.go
Voici toutes les options de GOTRACEBACK:
GOTRACEBACK=none
omet complètement les traces de la pile de goroutine.GOTRACEBACK=single
(le défaut) se comporte comme décrit ci-dessus.GOTRACEBACK=all
ajoute des traces de pile pour toutes les goroutines créées par l'utilisateur.GOTRACEBACK=system
est comme `` tout '' mais ajoute des cadres de pile pour les fonctions d'exécution et affiche les goroutines créées en interne par l'exécution.GOTRACEBACK=crash
est comme `` système '' mais se bloque d'une manière spécifique au système d'exploitation au lieu de quitter. Par exemple, sur les systèmes Unix, le crash SIGABRT
se déclenche pour déclencher un vidage de mémoire.La variable GOTRACEBACK contrôle la quantité de sortie générée lorsqu'un programme Go échoue en raison d'une panique non récupérée ou d'une condition d'exécution inattendue.
Par défaut, un échec imprime une trace de pile pour la goroutine actuelle, supprimant les fonctions internes au système d'exécution, puis se termine avec le code de sortie 2. L'échec imprime les traces de pile pour toutes les goroutines s'il n'y a pas de goroutine en cours ou si l'échec est interne au runtime.
Pour des raisons historiques, les paramètres GOTRACEBACK 0, 1 et 2 sont respectivement des synonymes de none, all et system.
La fonction SetTraceback du package d'exécution / débogage permet d'augmenter la quantité de sortie au moment de l'exécution, mais elle ne peut pas réduire la quantité en dessous de celle spécifiée par la variable d'environnement. Voir https://golang.org/pkg/runtime/debug/#SetTraceback .