[go] 고 루틴 스택 트레이스를 덤프하는 방법은 무엇입니까?

저는 Java 배경 지식이 있으며 Java 스레드 덤프를 검사하기 위해 신호 QUIT를 사용하는 것을 좋아합니다.

Golang이 모든 고 루틴 스택 추적을 인쇄하도록하는 방법은 무엇입니까?



답변

에 대한 스택 추적을 인쇄하려면 현재의 goroutine 사용 PrintStack()에서runtime/debug .

PrintStack은 Stack이 반환 한 스택 추적을 표준 오류로 인쇄합니다.

예를 들면 :

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-모든 현재 고 루틴
힙의
스택 추적- 모든 힙 할당의 샘플링 threadcreate-새 OS 스레드
블록 생성으로 이어진 스택 추적-동기화 기본 요소에 대한 차단으로 이어진 스택 추적

예를 들면 :

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


답변

runtime/pprofIntermernet의 답변에 언급 된 패키지에 대한 HTTP 프런트 엔드가 있습니다 . net / http / pprof 패키지를 가져와 다음에 대한 HTTP 처리기를 등록합니다 /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


답변

SIGQUIT에서 스택 덤프의 Java 동작을 모방하지만 프로그램을 계속 실행하려면 다음을 수행하십시오.

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


답변

Java와 마찬가지로 SIGQUIT는 Go 프로그램 및 해당 고 루틴의 스택 추적을 인쇄하는 데 사용할 수 있습니다.
그러나 주요 차이점은 기본적으로 SIGQUIT를 Java 프로그램에 전송하면 종료되지 않지만 Go 프로그램은 종료된다는 것입니다.

이 접근 방식은 기존 프로그램의 모든 고 루틴의 스택 추적을 인쇄하기 위해 코드를 변경할 필요가 없습니다.

환경 변수 GOTRACEBACK ( 런타임 패키지 설명서 참조 )은 생성되는 출력의 양을 제어합니다. 예를 들어 모든 고 루틴을 포함하려면 GOTRACEBACK = all을 설정합니다.

스택 추적의 인쇄는 원래이 commit에 문서화 된 예기치 않은 런타임 조건 (처리되지 않은 신호)에 의해 트리거되어 최소 Go 1.1 이후부터 사용할 수 있습니다.


또는 소스 코드 수정이 옵션 인 경우 다른 답변을 참조하십시오.


Linux 터미널에서 SIGQUIT는 Ctrl+ 키 조합을 사용하여 편리하게 전송할 수 있습니다 \.


답변

runtime.Stack 을 사용 하여 모든 고 루틴의 스택 추적을 가져올 수 있습니다 .

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

문서에서 :

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

Stack은 호출하는 goroutine의 스택 추적을 buf로 포맷하고 buf에 기록 된 바이트 수를 반환합니다. 모두 참이면 스택은 현재 고 루틴에 대한 추적 후에 다른 모든 고 루틴의 스택 추적을 buf로 형식화합니다.


답변

Ctrl + \를 누릅니다.

(터미널에서 실행하고 프로그램을 종료하고 go 루틴을 덤프하려는 경우)

이 질문은 키 시퀀스를 찾고 있습니다. 내 프로그램이 루틴을 유출하는지 빠르고 쉬운 방법을 원했습니다. 🙂


답변

* NIX 시스템 (OSX 포함)에서 abort 신호를 보냅니다 SIGABRT.

pkill -SIGABRT program_name