¿Cómo volcar stacktraces de goroutine?

Tengo antecedentes Java, y me encanta usar la señal QUIT para inspeccionar el volcado de subprocesos de Java.

¿Cómo dejar que Golang imprima todos los goroutines stack trace?

Para imprimir la traza de la stack para la rutina actual , use PrintStack() desde runtime/debug .

PrintStack imprime en el error estándar el seguimiento de stack devuelto por Stack.

Por ejemplo:

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

Para imprimir la traza de la stack para todos los goroutines use Lookup y WriteTo desde 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. 

Cada perfil tiene un nombre único. Algunos perfiles están predefinidos:

goroutine – stack de rastros de todos los goroutines actuales
montón: una muestra de todas las asignaciones de montón
threadcreate – stack trace que condujo a la creación de nuevos hilos del sistema operativo
block – stack traces que llevaron al locking en primitivas de sincronización

Por ejemplo:

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

Hay una interfaz HTTP para el paquete runtime/pprof mencionado en la respuesta de Intermernet. Importe el paquete net / http / pprof para registrar un controlador HTTP para /debug/pprof :

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

Inicie un escucha HTTP si aún no tiene uno:

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

A continuación, apunte un navegador a http://localhost:6060/debug/pprof para un menú, o http://localhost:6060/debug/pprof/goroutine?debug=2 para un volcado completo de stack de rutina.

También hay otras cosas divertidas que puedes aprender sobre tu código de ejecución. Consulte la publicación del blog para obtener ejemplos y más detalles: http://blog.golang.org/profiling-go-programs

Para imitar el comportamiento de Java de stack-dump en SIGQUIT pero aún dejando el progtwig en ejecución:

 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]) } }() 

Puede usar runtime.Stack para obtener el rastro de la stack de todos los goroutines:

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

De la documentación:

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

Stack formatea un rastro de stack de la rutina de llamadas en buf y devuelve el número de bytes escritos en buf. Si todo es verdad, los formatos Stack almacenan trazas de todas las otras rutinas en buf después de la traza de la rutina actual.

De acuerdo con los documentos del paquete de tiempo de ejecución , el envío de un SIGQUIT a un progtwig Go imprimirá, de forma predeterminada, un seguimiento de stack para cada rutina existente, eliminando funciones internas del sistema en tiempo de ejecución y luego saldrá con el código de salida 2.

La variable de entorno GOTRACEBACK controla la cantidad de salida generada. Para incluir todos los goroutines, sin filtro, establezca GOTRACEBACK = 2. Para generar adicionalmente un vuelco de núcleo (en sistemas Unix), establezca GOTRACEBACK = crash.

La documentación y la capacidad de generar volcados del núcleo se agregaron en este compromiso , y es, AFAICT, disponible desde Go 1.1.

Por lo tanto, este enfoque no requiere código para imprimir un seguimiento de la stack de todos los goroutines. La diferencia con Java es que Java seguirá ejecutando el progtwig, mientras que Go saldrá.

En los sistemas * NIX (incluido OSX) envía una señal de abortar SIGABRT :

pkill -SIGABRT program_name

Presione CTRL + \

(Si lo ejecuta en un terminal y solo quiere matar su progtwig y volcar las rutinas, etc.)

Encontré esta pregunta buscando la secuencia de teclas. Solo quería una manera rápida y fácil de saber si mi progtwig se está escapando, vaya a las rutinas 🙂

Es necesario usar la longitud devuelta por runtime.Stack() para evitar imprimir un montón de líneas vacías después del seguimiento de la stack. La siguiente función de recuperación imprime un rastro muy formateado:

 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])) }