2017-04-04 16 views
5

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を扱うことができる方法はありますか?

+0

「なぜあなたはこれをやりたいのですか?これはナルソだ」と私のシステムではユーザがテンプレートを作成できるということです。そして、テンプレートのレンダリング中に発生したエラーからメインランタイムを保護したい。現実の問題はgithub [ここ](https://github.com/bosun-monitor/bosun/issues/2054)です。 –

+2

ゴーファーの人々とチャットすると、sigsegvはプログラムを未定義の状態にしてしまい、安全に回復することができないと考えられます。 –

+1

「致命的なエラー」から回復することはできません。それは「パニック」ではありません – JimB

答えて

1

あなたがsigsegvに遭遇したとき、あなたは本当にプログラムの状態に関してすべてのベット・アクトの状況にあります。一般的に安全なことは、すべてを停止し、システムがデバッグのためにメモリにファイルをダンプすることです。これはGoと同じです。この状況では、「メインランタイムを保護する」方法はまったくありません。

信頼できないコードや安全でないコードを実行しているランタイムを使用している場合は、代わりに別のプロセスにコードを分離する必要があります。 が(ユーザー自身ではなく)ユーザーから受け取ったコードを実行している場合は、このプロセスを最も確実にサンドボックス化する必要があります。

だから私のアドバイスは、次のいずれかを実行します

  1. は、それがクラッシュしてみようと、ユーザはそこからそれを処理させます。 Goのsigsegvを引き起こすコードを書くユーザは、通常、足の方向に多かれ少なかれ活発な射撃を試みる必要があるので、彼ら自身の危険でやっている事の下ではまれに提出されるべきである。
  2. スーパーバイザプロセスと「信頼できない/安全でない」子プロセスに分けます。スーパープロセスは子プロセスから不適切な終了条件を取得し、適切に報告します。