Sto usando GO per verificare se un processo (non padre) ha terminato ben, in pratica qualcosa come il comando pwait in FreeBSD ma scritto in go.Come attendere correttamente che un evento/processo finisca di non essere il genitore?
Attualmente mi sto cercando un for loop
con un kill -0
, ma noto che l'utilizzo della CPU è molto elevato 99% con questo approccio, ecco il codice:
package main
import (
"fmt"
"os"
"strconv"
"syscall"
"time"
)
func main() {
if len(os.Args) != 2 {
fmt.Printf("usage: %s pid", os.Args[0])
os.Exit(1)
}
pid, err := strconv.ParseInt(os.Args[1], 10, 64)
if err != nil {
panic(err)
}
process, err := os.FindProcess(int(pid))
err = process.Signal(syscall.Signal(0))
for err == nil {
err = process.Signal(syscall.Signal(0))
time.Sleep(500 * time.Millisecond)
}
fmt.Println(err)
}
Qualsiasi idea di come migliorare o implementare correttamente questo.
Grazie in anticipo.
UPDATE
Aggiunta di un sleep
all'interno del ciclo, come suggerito, aiuta a ridurre il carico.
Dai collegamenti forniti, sembra essere possibile allegare al pid esistente, darò una prova PtraceAttach ma non so se questo può avere effetti collaterali, qualche idea?
Come suggerito che ero disponibile per l'uso kqueue:
package main
import (
"fmt"
"log"
"os"
"strconv"
"syscall"
)
func main() {
if len(os.Args) != 2 {
fmt.Printf("usage: %s pid", os.Args[0])
os.Exit(1)
}
pid, err := strconv.ParseInt(os.Args[1], 10, 64)
if err != nil {
panic(err)
}
process, _ := os.FindProcess(int(pid))
kq, err := syscall.Kqueue()
if err != nil {
fmt.Println(err)
}
ev1 := syscall.Kevent_t{
Ident: uint64(process.Pid),
Filter: syscall.EVFILT_PROC,
Flags: syscall.EV_ADD,
Fflags: syscall.NOTE_EXIT,
Data: 0,
Udata: nil,
}
for {
events := make([]syscall.Kevent_t, 1)
n, err := syscall.Kevent(kq, []syscall.Kevent_t{ev1}, events, nil)
if err != nil {
log.Println("Error creating kevent")
}
if n > 0 {
break
}
}
fmt.Println("fin")
}
funziona bene, ma chiedendosi come implementare/ottenere gli stessi su Linux dal penso kqueue
non disponibile su di esso, tutte le idee?
Alcune idee da questa domanda: [Come attendere l'uscita di processi non figli] (http://stackoverflow.com/q/1157700) –
Metti un breve sonno nel ciclo for. Linux non fornisce un modo efficiente per farlo – JimB
L'API 'kqueue' è utilizzabile da' go' (nel pacchetto 'syscall'), e se la portabilità non è richiesta, oltre a * BSD e Darwin, quindi il BSD' pwait 'l'utilità potrebbe essere tradotta in' go'. – kdhp