signal package状態:SIGBUS、SIGFPE、およびSIGSEGV:リカバリでSIGSEGVを扱う?
同期信号は、プログラム 実行中のエラーによりトリガー信号です。これらは、 os.Process.Killまたはkillプログラムまたは同様のメカニズムを使用して送信されたときではなく、プログラムの実行によって発生した場合に限り、同期したとみなされます。 一般的には、以下で説明する場合を除き、Goプログラムは 同期信号を実行時パニックに変換します。
しかし、recover()
はこれをキャッチしていないようです。
プログラム:
package main
import (
"fmt"
"unsafe"
"log"
)
func seeAnotherDay() {
defer func() {
if p := recover(); p != nil {
err := fmt.Errorf("recover panic: panic call")
log.Println(err)
return
}
}()
panic("oops")
}
func notSoMuch() {
defer func() {
if p := recover(); p != nil {
err := fmt.Errorf("recover panic: sigseg")
log.Println(err)
return
}
}()
b := make([]byte, 1)
log.Println("access some memory")
foo := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(9999999999999999)))
fmt.Print(*foo + 1)
}
func main() {
seeAnotherDay()
notSoMuch()
}
出力:
2017/04/04 12:13:16 recover panic: panic call
2017/04/04 12:13:16 access some memory
unexpected fault address 0xb01dfacedebac1e
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x1 addr=0xb01dfacedebac1e pc=0x108aa8a]
goroutine 1 [running]:
runtime.throw(0x10b5807, 0x5)
/usr/local/go/src/runtime/panic.go:596 +0x95 fp=0xc420043ea8 sp=0xc420043e88
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:297 +0x28c fp=0xc420043ef8 sp=0xc420043ea8
main.notSoMuch()
/Users/kbrandt/src/sigseg/main.go:32 +0xca fp=0xc420043f78 sp=0xc420043ef8
main.main()
/Users/kbrandt/src/sigseg/main.go:37 +0x25 fp=0xc420043f88 sp=0xc420043f78
runtime.main()
/usr/local/go/src/runtime/proc.go:185 +0x20a fp=0xc420043fe0 sp=0xc420043f88
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:2197 +0x1 fp=0xc420043fe8 sp=0xc420043fe0
exit status 2
は、私は、コードの特定の部分に局在した方法でSIGSEGVを扱うことができる方法はありますか?
「なぜあなたはこれをやりたいのですか?これはナルソだ」と私のシステムではユーザがテンプレートを作成できるということです。そして、テンプレートのレンダリング中に発生したエラーからメインランタイムを保護したい。現実の問題はgithub [ここ](https://github.com/bosun-monitor/bosun/issues/2054)です。 –
ゴーファーの人々とチャットすると、sigsegvはプログラムを未定義の状態にしてしまい、安全に回復することができないと考えられます。 –
「致命的なエラー」から回復することはできません。それは「パニック」ではありません – JimB