Tenho experiência em Java e adoro usar o sinal QUIT para inspecionar o despejo de thread do Java.
Como deixar Golang imprimir todos os rastreamentos de pilha de goroutines?
Tenho experiência em Java e adoro usar o sinal QUIT para inspecionar o despejo de thread do Java.
Como deixar Golang imprimir todos os rastreamentos de pilha de goroutines?
Respostas:
Para imprimir o rastreamento de pilha da goroutine atual , use PrintStack()deruntime/debug .
PrintStack imprime em erro padrão o rastreamento de pilha retornado por Stack.
Por exemplo:
import(
"runtime/debug"
)
...
debug.PrintStack()
Para imprimir o rastreamento de pilha para todos os goroutines, use Lookupe WriteTode 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 possui um nome único. Alguns perfis são predefinidos:
goroutine - rastreamentos de pilha de todos os
heap goroutines atuais - uma amostra de todas as alocações de heap
threadcreate - rastreamentos de pilha que levaram à criação de novos threads de sistema operacional
bloco - rastreamentos de pilha que levaram ao bloqueio de primitivos de sincronização
Por exemplo:
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
Stack. "Stack retorna um rastreamento de pilha formatado da goroutine que a chama. Para cada rotina, inclui as informações da linha de origem e o valor do PC, em seguida, tenta descobrir, para funções Go, a função ou método de chamada e o texto da linha que contém o invocação."
Existe um frontend HTTP para o runtime/pprofpacote mencionado na resposta da Intermernet. Importe o pacote net / http / pprof para registrar um manipulador HTTP para /debug/pprof:
import _ "net/http/pprof"
import _ "net/http"
Inicie um ouvinte HTTP, se ainda não tiver um:
go func() {
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
Em seguida, aponte um navegador http://localhost:6060/debug/pprofpara um menu ou http://localhost:6060/debug/pprof/goroutine?debug=2para um despejo de pilha goroutine completo.
Existem outras coisas divertidas que você pode aprender sobre o código em execução dessa maneira também. Confira a postagem do blog para exemplos e mais detalhes: http://blog.golang.org/profiling-go-programs
Para imitar o comportamento do Java de despejo de pilha no SIGQUIT, mas ainda deixando o programa em execução:
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])
}
}()
Semelhante ao Java, SIGQUIT pode ser usado para imprimir um rastreamento de pilha de um programa Go e suas goroutines.
Uma diferença chave, entretanto, é que por padrão o envio de SIGQUIT para programas Java não os encerra, enquanto os programas Go são encerrados.
Esta abordagem não requer nenhuma mudança de código para imprimir um rastreamento de pilha de todos os goroutines de programas existentes.
A variável de ambiente GOTRACEBACK ( consulte a documentação do pacote runtime ) controla a quantidade de saída gerada. Por exemplo, para incluir todas as goroutines, defina GOTRACEBACK = all.
A impressão do rastreamento de pilha é acionada por uma condição de tempo de execução inesperada (sinal não tratado), originalmente documentado neste commit , tornando-o disponível desde pelo menos Go 1.1.
Como alternativa, se modificar o código-fonte for uma opção, consulte outras respostas.
Observe que em um terminal Linux, SIGQUIT pode ser enviado convenientemente com a combinação de teclas Ctrl+ \.
Você pode usar runtime.Stack para obter o rastreamento de pilha de todos os goroutines:
buf := make([]byte, 1<<16)
runtime.Stack(buf, true)
fmt.Printf("%s", buf)
Da documentação:
func Stack(buf []byte, all bool) int
Stack formata um rastreamento de pilha da goroutine de chamada em buf e retorna o número de bytes gravados em buf. Se tudo for verdade, Stack formata os rastreamentos de pilha de todas as outras goroutines em buf após o rastreio da goroutine atual.
string(buf)aqui, fmt.Printf("%s", buf)e fmt.Printf("%s", string(buf))fazer exatamente a mesma coisa (veja a documentação do fmtpacote); a única diferença aqui é que a stringversão irá copiar os bytes de bufdesnecessariamente
Pressione CTRL + \
(Se você executá-lo em um terminal e só quiser encerrar seu programa e descartar as rotinas go, etc.)
Encontrei esta questão procurando a sequência chave. Só queria uma maneira rápida e fácil de saber se meu programa está vazando rotinas de go :)
Em sistemas * NIX (incluindo OSX), envie um sinal de cancelamento SIGABRT:
pkill -SIGABRT program_name
É necessário usar o comprimento retornado por runtime.Stack()para evitar a impressão de um monte de linhas vazias após o rastreamento da pilha. A seguinte função de recuperação imprime um rastreamento bem formatado:
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]))
}
Por padrão, pressione as ^\teclas ( CTRL + \ ) para despejar os rastreamentos de pilha de todas as goroutines.
Caso contrário, para um controle mais granular, você pode usar panic. A maneira simples a partir do Go 1.6+ :
go func() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
Em seguida, execute seu programa assim:
# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go
Se você também deseja imprimir goroutines go runtime:
$ GOTRACEBACK=system go run main.go
Aqui estão todas as opções GOTRACEBACK:
GOTRACEBACK=none omite os rastreamentos de pilha goroutine inteiramente.GOTRACEBACK=single (o padrão) se comporta conforme descrito acima.GOTRACEBACK=all adiciona rastreamentos de pilha para todas as goroutines criadas pelo usuário.GOTRACEBACK=system é como `` all '', mas adiciona frames de pilha para funções de tempo de execução e mostra goroutinas criadas internamente pelo tempo de execução.GOTRACEBACK=crashé como o `` sistema '', mas trava de maneira específica do sistema operacional ao invés de sair. Por exemplo, em sistemas Unix, a falha aumenta SIGABRTpara acionar um despejo de memória.A variável GOTRACEBACK controla a quantidade de saída gerada quando um programa Go falha devido a um pânico não recuperado ou uma condição de tempo de execução inesperada.
Por padrão, uma falha imprime um rastreamento de pilha para a goroutine atual, elidindo funções internas ao sistema de tempo de execução e, em seguida, sai com o código de saída 2. A falha imprime rastreamentos de pilha para todas as goroutines se não houver goroutine atual ou a falha for interno ao tempo de execução.
Por razões históricas, as configurações GOTRACEBACK 0, 1 e 2 são sinônimos para nenhum, todos e sistema, respectivamente.
A função SetTraceback do pacote de tempo de execução / depuração permite aumentar a quantidade de saída em tempo de execução, mas não pode reduzir a quantidade abaixo daquela especificada pela variável de ambiente. Consulte https://golang.org/pkg/runtime/debug/#SetTraceback .