Beispiel #1
0
// Detach from the process being debugged, optionally killing it.
func (dbp *Process) Detach(kill bool) (err error) {
	if dbp.Running() {
		if err = dbp.Halt(); err != nil {
			return
		}
	}
	if !kill {
		// Clean up any breakpoints we've set.
		for _, bp := range dbp.Breakpoints {
			if bp != nil {
				_, err := dbp.ClearBreakpoint(bp.Addr)
				if err != nil {
					return err
				}
			}
		}
	}
	dbp.execPtraceFunc(func() {
		err = PtraceDetach(dbp.Pid, 0)
		if err != nil {
			return
		}
		if kill {
			err = sys.Kill(dbp.Pid, sys.SIGINT)
		}
	})
	return
}
Beispiel #2
0
func (d *Debugger) Restart() error {
	if !d.process.Exited() {
		if d.process.Running() {
			d.process.Halt()
		}
		// Ensure the process is in a PTRACE_STOP.
		if err := sys.Kill(d.ProcessPid(), sys.SIGSTOP); err != nil {
			return err
		}
		if err := d.Detach(true); err != nil {
			return err
		}
	}
	p, err := proc.Launch(d.config.ProcessArgs)
	if err != nil {
		return fmt.Errorf("could not launch process: %s", err)
	}
	for addr, bp := range d.process.Breakpoints {
		if bp.Temp {
			continue
		}
		if _, err := p.SetBreakpoint(addr); err != nil {
			return err
		}
	}
	d.process = p
	return nil
}
Beispiel #3
0
func (dbp *Process) Kill() (err error) {
	if !stopped(dbp.Pid) {
		return errors.New("process must be stopped in order to kill it")
	}
	err = sys.Kill(dbp.Pid, sys.SIGKILL)
	if err != nil {
		return errors.New("could not deliver signal " + err.Error())
	}
	_, _, err = wait(-1, dbp.Pid, 0)
	if err != nil {
		return
	}
	dbp.exited = true
	return
}
Beispiel #4
0
func (dbp *Process) Kill() (err error) {
	if dbp.exited {
		return nil
	}
	if !dbp.Threads[dbp.Pid].Stopped() {
		return errors.New("process must be stopped in order to kill it")
	}
	if err = sys.Kill(-dbp.Pid, sys.SIGKILL); err != nil {
		return errors.New("could not deliver signal " + err.Error())
	}
	if _, _, err = wait(dbp.Pid, dbp.Pid, 0); err != nil {
		return
	}
	dbp.exited = true
	return
}
Beispiel #5
0
func (dbp *Process) Kill() (err error) {
	err = sys.Kill(dbp.Pid, sys.SIGKILL)
	if err != nil {
		return errors.New("could not deliver signal: " + err.Error())
	}
	for port := range dbp.Threads {
		if C.thread_resume(C.thread_act_t(port)) != C.KERN_SUCCESS {
			return errors.New("could not resume task")
		}
	}
	for {
		port := C.mach_port_wait(dbp.os.portSet)
		if port == dbp.os.notificationPort {
			break
		}
	}
	dbp.exited = true
	return
}
Beispiel #6
0
func (d *Debugger) Restart() error {
	if !d.process.Exited() {
		if d.process.Running() {
			d.process.Halt()
		}
		// Ensure the process is in a PTRACE_STOP.
		if err := sys.Kill(d.ProcessPid(), sys.SIGSTOP); err != nil {
			return err
		}
		if err := d.Detach(true); err != nil {
			return err
		}
	}
	p, err := proc.Launch(d.config.ProcessArgs)
	if err != nil {
		return fmt.Errorf("could not launch process: %s", err)
	}
	d.process = p
	return nil
}
Beispiel #7
0
func (dbp *Process) requestManualStop() (err error) {
	return sys.Kill(dbp.Pid, sys.SIGTRAP)
}
Beispiel #8
0
func killProcess(pid int) error {
	return sys.Kill(pid, sys.SIGINT)
}
Beispiel #9
0
func TerminateProcess(pid int) {
	unix.Kill(pid, unix.SIGTERM)
}
Beispiel #10
0
func SuspendProcess(pid int) {
	unix.Kill(pid, unix.SIGSTOP)
}
Beispiel #11
0
func ContinueProcess(pid int) {
	unix.Kill(pid, unix.SIGCONT)
}
Beispiel #12
0
func stopProcess(pid int) error {
	return sys.Kill(pid, sys.SIGSTOP)
}
Beispiel #13
0
func (p *process) handleSigkilledShim(rst int, rerr error) (int, error) {
	if p.cmd == nil || p.cmd.Process == nil {
		e := unix.Kill(p.pid, 0)
		if e == syscall.ESRCH {
			return rst, rerr
		}

		// If it's not the same process, just mark it stopped and set
		// the status to 255
		if same, err := p.isSameProcess(); !same {
			logrus.Warnf("containerd: %s:%s (pid %d) is not the same process anymore (%v)", p.container.id, p.id, p.pid, err)
			p.stateLock.Lock()
			p.state = Stopped
			p.stateLock.Unlock()
			// Create the file so we get the exit event generated once monitor kicks in
			// without going to this all process again
			rerr = ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte("255"), 0644)
			return 255, nil
		}

		ppid, err := readProcStatField(p.pid, 4)
		if err != nil {
			return rst, fmt.Errorf("could not check process ppid: %v (%v)", err, rerr)
		}
		if ppid == "1" {
			logrus.Warnf("containerd: %s:%s shim died, killing associated process", p.container.id, p.id)
			unix.Kill(p.pid, syscall.SIGKILL)
			// wait for the process to die
			for {
				e := unix.Kill(p.pid, 0)
				if e == syscall.ESRCH {
					break
				}
				time.Sleep(10 * time.Millisecond)
			}

			rst = 128 + int(syscall.SIGKILL)
			// Create the file so we get the exit event generated once monitor kicks in
			// without going to this all process again
			rerr = ioutil.WriteFile(filepath.Join(p.root, ExitStatusFile), []byte(fmt.Sprintf("%d", rst)), 0644)
		}

		return rst, rerr
	}

	// Possible that the shim was SIGKILLED
	e := unix.Kill(p.cmd.Process.Pid, 0)
	if e != syscall.ESRCH {
		return rst, rerr
	}

	// Ensure we got the shim ProcessState
	<-p.cmdDoneCh

	shimStatus := p.cmd.ProcessState.Sys().(syscall.WaitStatus)
	if shimStatus.Signaled() && shimStatus.Signal() == syscall.SIGKILL {
		logrus.Debugf("containerd: ExitStatus(container: %s, process: %s): shim was SIGKILL'ed reaping its child with pid %d", p.container.id, p.id, p.pid)

		var (
			status unix.WaitStatus
			rusage unix.Rusage
			wpid   int
		)

		// Some processes change their PR_SET_PDEATHSIG, so force kill them
		unix.Kill(p.pid, syscall.SIGKILL)

		for wpid == 0 {
			wpid, e = unix.Wait4(p.pid, &status, unix.WNOHANG, &rusage)
			if e != nil {
				logrus.Debugf("containerd: ExitStatus(container: %s, process: %s): Wait4(%d): %v", p.container.id, p.id, p.pid, rerr)
				return rst, rerr
			}
		}

		if wpid == p.pid {
			rerr = nil
			rst = 128 + int(shimStatus.Signal())
		} else {
			logrus.Errorf("containerd: ExitStatus(container: %s, process: %s): unexpected returned pid from wait4 %v (expected %v)", p.container.id, p.id, wpid, p.pid)
		}

		p.stateLock.Lock()
		p.state = Stopped
		p.stateLock.Unlock()
	}

	return rst, rerr
}
Beispiel #14
0
func TestReap_ReapChildren(t *testing.T) {
	pids := make(PidCh, 1)
	errors := make(ErrorCh, 1)
	done := make(chan struct{}, 1)
	var reapLock sync.RWMutex

	didExit := make(chan struct{}, 1)
	go func() {
		ReapChildren(pids, errors, done, &reapLock)
		didExit <- struct{}{}
	}()

	killAndCheck := func() {
		cmd := exec.Command("sleep", "5")
		if err := cmd.Start(); err != nil {
			t.Fatalf("err: %v", err)
		}

		childPid := cmd.Process.Pid
		if err := cmd.Process.Kill(); err != nil {
			t.Fatalf("err: %v", err)
		}

		select {
		case pid := <-pids:
			if pid != childPid {
				t.Fatalf("unexpected pid: %d != %d", pid, childPid)
			}
		case err := <-errors:
			t.Fatalf("err: %v", err)
		case <-time.After(1 * time.Second):
			t.Fatalf("should have reaped %d", childPid)
		}
	}

	// Kill a child process and make sure it gets detected.
	killAndCheck()

	// Fire off a subprocess.
	cmd := exec.Command("sleep", "5")
	if err := cmd.Start(); err != nil {
		t.Fatalf("err: %v", err)
	}

	// Send a spurious SIGCHLD.
	if err := unix.Kill(os.Getpid(), unix.SIGCHLD); err != nil {
		t.Fatalf("err: %v", err)
	}

	// Make sure the reaper didn't report anything.
	select {
	case pid := <-pids:
		t.Fatalf("unexpected pid: %d", pid)
	case err := <-errors:
		t.Fatalf("err: %v", err)
	case <-time.After(1 * time.Second):
		// Good - nothing was sent to the channels.
	}

	// Take the reap lock.
	reapLock.RLock()

	// Now kill the child subprocess.
	childPid := cmd.Process.Pid
	if err := cmd.Process.Kill(); err != nil {
		t.Fatalf("err: %v", err)
	}

	// Make sure the reaper didn't report anything.
	select {
	case pid := <-pids:
		t.Fatalf("unexpected pid: %d", pid)
	case err := <-errors:
		t.Fatalf("err: %v", err)
	case <-time.After(1 * time.Second):
		// Good - nothing was sent to the channels.
	}

	// Give up the reap lock.
	reapLock.RUnlock()

	// Make sure the reaper sees it.
	select {
	case pid := <-pids:
		if pid != childPid {
			t.Fatalf("unexpected pid: %d != %d", pid, childPid)
		}
	case err := <-errors:
		t.Fatalf("err: %v", err)
	case <-time.After(1 * time.Second):
		t.Fatalf("should have reaped %d", childPid)
	}

	// Run a few more cycles to make sure things work.
	killAndCheck()
	killAndCheck()
	killAndCheck()

	// Shut it down.
	close(done)
	select {
	case <-didExit:
		// Good - the goroutine shut down.
	case <-time.After(1 * time.Second):
		t.Fatalf("should have shut down")
	}
}