From 4da4aea89c4fe6106fa2ef0666f284ba6752d701 Mon Sep 17 00:00:00 2001 From: aarzilli Date: Thu, 7 Jan 2016 19:33:15 +0100 Subject: [PATCH] proc: wait for full process stop before evaluating anything --- proc/proc_darwin.c | 2 +- proc/proc_darwin.go | 33 ++++++++++++++++++++++++++++----- proc/threads_darwin.c | 33 +++++++++++++++++++++++++++++++++ proc/threads_darwin.h | 3 +++ 4 files changed, 65 insertions(+), 6 deletions(-) diff --git a/proc/proc_darwin.c b/proc/proc_darwin.c index 25e2a9f7..4d17c54d 100644 --- a/proc/proc_darwin.c +++ b/proc/proc_darwin.c @@ -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; diff --git a/proc/proc_darwin.go b/proc/proc_darwin.go index e11b9aa7..fa291be2 100644 --- a/proc/proc_darwin.go +++ b/proc/proc_darwin.go @@ -1,6 +1,7 @@ package proc // #include "proc_darwin.h" +// #include "threads_darwin.h" // #include "exec_darwin.h" // #include 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) { diff --git a/proc/threads_darwin.c b/proc/threads_darwin.c index 51d0e97a..16f7a6da 100644 --- a/proc/threads_darwin.c +++ b/proc/threads_darwin.c @@ -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; +} diff --git a/proc/threads_darwin.h b/proc/threads_darwin.h index 4a64d49d..a77d434d 100644 --- a/proc/threads_darwin.h +++ b/proc/threads_darwin.h @@ -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);