func suspend(g *godit) { // finalize termbox termbox.Close() // suspend the process pid := syscall.Getpid() tid := syscall.Gettid() err := syscall.Tgkill(pid, tid, syscall.SIGSTOP) if err != nil { panic(err) } // reset the state so we can get back to work again err = termbox.Init() if err != nil { panic(err) } termbox.SetInputMode(termbox.InputAlt) g.resize() }
// StopTracing stops tracing all threads for the given pid func (t *PTracer) StopTracing(pid int) error { log.Printf("Detaching from %d", pid) errors := make(chan error) processes := make(chan *process) t.ops <- func() { // send sigstop to all threads process, ok := t.processes[pid] if !ok { errors <- fmt.Errorf("PID %d not found", pid) return } // This flag tells the thread to detach when it next stops process.detaching = true // Now send sigstop to all threads. for _, thread := range process.threads { log.Printf("sending SIGSTOP to %d", thread.tid) if err := syscall.Tgkill(pid, thread.tid, syscall.SIGSTOP); err != nil { errors <- err return } } processes <- process } select { case err := <-errors: return err case process := <-processes: <-process.detached return nil } }
// sendSigstop sends a SIGSTOP to this thread. func (t *thread) sendSigstop() os.Error { t.logTrace("sending SIGSTOP") err := syscall.Tgkill(t.proc.pid, t.tid, syscall.SIGSTOP) return os.NewSyscallError("tgkill", err) }