mirror of
https://github.com/go-delve/delve.git
synced 2025-10-29 09:46:56 +08:00
proc: wait for full process stop before evaluating anything
This commit is contained in:
@ -127,7 +127,7 @@ mach_port_wait(mach_port_t port_set, int nonblocking) {
|
||||
|
||||
// Wait for mach msg.
|
||||
kret = mach_msg(&msg.hdr, opts,
|
||||
0, sizeof(msg.data), port_set, 0, MACH_PORT_NULL);
|
||||
0, sizeof(msg.data), port_set, 10, MACH_PORT_NULL);
|
||||
if (kret == MACH_RCV_INTERRUPTED) return kret;
|
||||
if (kret != MACH_MSG_SUCCESS) return 0;
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package proc
|
||||
|
||||
// #include "proc_darwin.h"
|
||||
// #include "threads_darwin.h"
|
||||
// #include "exec_darwin.h"
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
@ -314,20 +315,42 @@ func (dbp *Process) trapWait(pid int) (*Thread, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
|
||||
trapthread.SetCurrentBreakpoint()
|
||||
func (dbp *Process) waitForStop() ([]int, error) {
|
||||
ports := make([]int, 0, len(dbp.Threads))
|
||||
count := 0
|
||||
for {
|
||||
port := C.mach_port_wait(dbp.os.portSet, C.int(1))
|
||||
if port == 0 {
|
||||
return nil
|
||||
if port != 0 {
|
||||
count = 0
|
||||
ports = append(ports, int(port))
|
||||
} else {
|
||||
n := C.num_running_threads(C.task_t(dbp.os.task))
|
||||
if n == 0 {
|
||||
return ports, nil
|
||||
} else if n < 0 {
|
||||
return nil, fmt.Errorf("error waiting for thread stop %d", n)
|
||||
} else if count > 16 {
|
||||
return nil, fmt.Errorf("could not stop porcess %d", n)
|
||||
}
|
||||
}
|
||||
if th, ok := dbp.Threads[int(port)]; ok {
|
||||
}
|
||||
}
|
||||
|
||||
func (dbp *Process) setCurrentBreakpoints(trapthread *Thread) error {
|
||||
ports, err := dbp.waitForStop()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
trapthread.SetCurrentBreakpoint()
|
||||
for _, port := range ports {
|
||||
if th, ok := dbp.Threads[port]; ok {
|
||||
err := th.SetCurrentBreakpoint()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dbp *Process) loadProcessInformation(wg *sync.WaitGroup) {
|
||||
|
||||
@ -135,3 +135,36 @@ thread_blocked(thread_act_t thread) {
|
||||
|
||||
return info.suspend_count;
|
||||
}
|
||||
|
||||
int
|
||||
num_running_threads(task_t task) {
|
||||
kern_return_t kret;
|
||||
thread_act_array_t list;
|
||||
mach_msg_type_number_t count;
|
||||
int i, n = 0;
|
||||
|
||||
kret = task_threads(task, &list, &count);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return -kret;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; ++i) {
|
||||
thread_act_t thread = list[i];
|
||||
struct thread_basic_info info;
|
||||
unsigned int info_count = THREAD_BASIC_INFO_COUNT;
|
||||
|
||||
kret = thread_info((thread_t)thread, THREAD_BASIC_INFO, (thread_info_t)&info, &info_count);
|
||||
|
||||
if (kret == KERN_SUCCESS) {
|
||||
if (info.suspend_count == 0) {
|
||||
++n;
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kret = vm_deallocate(mach_task_self(), (vm_address_t) list, count * sizeof(list[0]));
|
||||
if (kret != KERN_SUCCESS) return -kret;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -33,3 +33,6 @@ get_identity(mach_port_name_t, thread_identifier_info_data_t *);
|
||||
|
||||
int
|
||||
thread_blocked(thread_act_t thread);
|
||||
|
||||
int
|
||||
num_running_threads(task_t task);
|
||||
|
||||
Reference in New Issue
Block a user