У меня есть опыт работы с Java, и я люблю использовать сигнал QUIT для проверки дампа потока Java.
Как позволить Golang распечатать трассировку стека всех горутин?
У меня есть опыт работы с Java, и я люблю использовать сигнал QUIT для проверки дампа потока Java.
Как позволить Golang распечатать трассировку стека всех горутин?
Ответы:
Чтобы распечатать трассировку стека для текущей горутины, используйте PrintStack()
fromruntime/debug
.
PrintStack печатает до стандартной ошибки трассировку стека, возвращаемую Stack.
Например:
import(
"runtime/debug"
)
...
debug.PrintStack()
Чтобы распечатать трассировку стека для всех горутин, используйте 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 - трассировки стека, которые привели к созданию нового
блока потоков ОС - трассировки стека, которые привели к блокировке примитивов синхронизации
Например:
pprof.Lookup("goroutine").WriteTo(os.Stdout, 1)
Stack
. "Стек возвращает отформатированную трассировку стека горутины, которая его вызывает. Для каждой процедуры он включает информацию о строке источника и значение ПК, а затем пытается обнаружить для функций Go вызывающую функцию или метод и текст строки, содержащей призыв ".
Существует HTTP-интерфейс для runtime/pprof
пакета, упомянутого в ответе Intermernet. Импортируйте пакет 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
Чтобы имитировать поведение Java при выводе дампа стека при SIGQUIT, но при этом оставив программу работающей:
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.
Печать трассировки стека запускается неожиданным условием выполнения (необработанный сигнал), изначально задокументированным в этом коммите , что делает его доступным по крайней мере с версии 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
Стек форматирует трассировку стека вызывающей горутины в buf и возвращает количество байтов, записанных в buf. Если все верно, Stack форматирует трассировки стека всех других горутин в buf после трассировки для текущей горутины.
string(buf)
здесь, fmt.Printf("%s", buf)
и fmt.Printf("%s", string(buf))
сделать то же самое (см документации для fmt
пакета); единственная разница здесь в том, что string
версия будет копировать байты buf
без нужды
Нажмите CTRL + \
(Если вы запускаете его в терминале и просто хотите убить свою программу и сбросить подпрограммы go и т. Д.)
Я нашел этот вопрос в поисках ключевой последовательности. Просто хотел быстрый и простой способ узнать, не утекает ли моя программа подпрограммы go :)
В системах * NIX (включая OSX) отправьте сигнал прерывания SIGABRT
:
pkill -SIGABRT program_name
Необходимо использовать длину, возвращаемую до, runtime.Stack()
чтобы не печатать кучу пустых строк после трассировки стека. Следующая функция восстановления распечатывает красиво отформатированную трассировку:
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]))
}
По умолчанию нажмите ^\
клавиши ( CTRL + \ ), чтобы выгрузить трассировку стека всех горутин.
В противном случае для более детального контроля вы можете использовать panic
. Простой способ для Go 1.6+ :
go func() {
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGQUIT)
<-s
panic("give me the stack")
}()
Затем запустите вашу программу так:
# Press ^\ to dump the stack traces of all the user-created goroutines
$ GOTRACEBACK=all go run main.go
Если вы также хотите распечатать горутины времени выполнения:
$ GOTRACEBACK=system go run main.go
Вот все варианты GOTRACEBACK:
GOTRACEBACK=none
полностью исключает трассировку стека горутин.GOTRACEBACK=single
(по умолчанию) ведет себя, как описано выше.GOTRACEBACK=all
добавляет трассировки стека для всех горутин, созданных пользователем.GOTRACEBACK=system
похож на `` все '', но добавляет фреймы стека для функций времени выполнения и показывает горутины, созданные внутри среды выполнения.GOTRACEBACK=crash
похоже на `` систему '', но вместо выхода происходит сбой в зависимости от операционной системы. Например, в системах Unix возникает сбой, вызывающий SIGABRT
дамп ядра.Переменная GOTRACEBACK контролирует количество выходных данных, генерируемых при сбое программы Go из-за невосстановленной паники или неожиданного условия выполнения.
По умолчанию при сбое печатается трассировка стека для текущей горутины, исключаются функции, внутренние для системы времени выполнения, и затем выполняется выход с кодом выхода 2. При сбое печатаются трассировки стека для всех горутин, если текущей горутины нет или сбой произошел. внутренний по отношению к времени выполнения.
По историческим причинам настройки GOTRACEBACK 0, 1 и 2 являются синонимами для none, all и system соответственно.
Функция SetTraceback пакета среды выполнения / отладки позволяет увеличить объем вывода во время выполнения, но не может уменьшить объем ниже указанного в переменной среды. См. Https://golang.org/pkg/runtime/debug/#SetTraceback .