2014-04-29 13 views
7

Un processo Go è in esecuzione. VoglioCome posso scaricare tutti gli stack di un processo Go?

  1. dump di un analisi dello stack per ciascuno dei suoi goroutines
  2. dall'esterno, senza dipendere da qualcosa che si aggiungono al suo codice sorgente
  3. senza ucciderlo.

Come posso farlo?

Questo dovrebbe essere facile - la funzionalità è stata richiesta: https://code.google.com/p/go/issues/detail?id=2516 e, in base alla conclusione di tale thread, implementata. È stato più di due anni fa. Ma né il thread del problema né il commit contengono alcun suggerimento su come richiamare questa funzione.

La richiesta di funzionalità ha indicato che SIGQUIT richiama la funzione corrispondente sulla JVM, ma non è così; almeno su go1.2, SIGQUIT fa # 1 e # 2 ma uccide anche il processo.

Qualcuno ha chiesto una questione connessa qui qualche tempo fa: How to dump goroutine stacktraces? ma non hanno chiaramente chiedere 2 o # 3 #, nessuna delle risposte incontrano # 2, e hanno accettato una risposta che non soddisfa 2 # . Quindi questa è una domanda diversa.

+2

Sembra che tu debba aggiungere qualcosa al programma per catturare SIGQUIT ed eseguire il codice nella risposta che hai collegato. Non vedo nulla nella lista delle modifiche di Brad che suggerisca di aggiungere un gestore di segnale predefinito o qualcosa del genere. – twotwotwo

risposta

3

Se si utilizza net/http è possibile accedere alle goroutine tramite i gestori debug. Se si guarda alla seguente origine

http://golang.org/src/pkg/runtime/pprof/pprof.go

Vedrete il profilo, goroutineProfile, sulla linea 62. Questo profilo scrive via writeGoroutine. Se writeGoroutine viene chiamato con debug> = 2 allora scriverà tutte le goroutine.

Dovresti essere in grado di curl http://localhost:<port>/debug/pprof/goroutine?debug=2 per scaricare tutte le goroutine. Sfortunatamente non ho visto alcun riferimento ai gestori di segnali che chiamerebbero quel codice, ma puoi consultare i riferimenti a come pprof utilizza runtime.Stack nella fonte sopra per implementare questo da solo abbastanza facilmente.

9

È possibile impostare un gestore del genere codice utilizzando qualcosa di simile:

import (
    "fmt" 
    "os" 
    "os/signal" 
    "runtime" 
    "syscall" 
) 

func main() { 
    sigChan := make(chan os.Signal) 
    go func() { 
     stacktrace := make([]byte, 8192) 
     for _ = range sigChan { 
      length := runtime.Stack(stacktrace, true) 
      fmt.Println(string(stacktrace[:length])) 
     } 
    }() 
    signal.Notify(sigChan, syscall.SIGQUIT) 


    ... 
} 

Il segnale SIGQUIT sarà ora preso e inviato al canale specificato. La funzione runtime.Stack viene quindi utilizzata per formattare la traccia dello stack in un buffer preparato (se è più grande del buffer, verrà troncato) e quindi stampato.

+0

Non soddisfa il requisito n. 2 – Bryan

Problemi correlati