agent/src/os/bsd/MacosxDebuggerLocal.m

Print this page
rev 4134 : 8008102: SA on OS X does not stop the attached process
Reviewed-by:

*** 36,45 **** --- 36,47 ---- #import <stdlib.h> #import <strings.h> #import <dlfcn.h> #import <limits.h> #import <errno.h> + #import <sys/types.h> + #import <sys/ptrace.h> jboolean debug = JNI_FALSE; static jfieldID symbolicatorID = 0; // set in _init0 static jfieldID taskID = 0; // set in _init0
*** 444,462 **** --- 446,485 ---- debug = JNI_TRUE; else debug = JNI_FALSE; if (debug) printf("attach0 called for jpid=%d\n", (int)jpid); + // get the task from the pid kern_return_t result; task_t gTask = 0; result = task_for_pid(mach_task_self(), jpid, &gTask); if (result != KERN_SUCCESS) { fprintf(stderr, "attach: task_for_pid(%d) failed (%d)\n", (int)jpid, result); THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); } putTask(env, this_obj, gTask); + // use ptrace to stop the process + // on os x, ptrace only needs to be called on the process, not the individual threads + int res, status; + res = ptrace(PT_ATTACH, jpid, 0, 0); + if (res < 0) { + fprintf(stderr, "attach: ptrace(PT_ATTACH, %d) failed (%d)\n", (int)jpid, res); + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); + } + + res = waitpid(jpid, &status, 0); + if (res < 0) { + fprintf(stderr, "attach: waitpid(%d) failed (%d, %d)\n", (int)jpid, res, errno); + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); + } + + if (! WIFSTOPPED(status)) { + fprintf(stderr, "attach: stopping the process failed %d\n", status); + THROW_NEW_DEBUGGER_EXCEPTION("Can't attach to the process"); + } + id symbolicator = nil; id jrsSymbolicator = objc_lookUpClass("JRSSymbolicator"); if (jrsSymbolicator != nil) { id (*dynamicCall)(id, SEL, pid_t) = (id (*)(id, SEL, pid_t))&objc_msgSend; symbolicator = dynamicCall(jrsSymbolicator, @selector(symbolicatorForPid:), (pid_t)jpid);
*** 484,493 **** --- 507,531 ---- { JNF_COCOA_ENTER(env); if (debug) printf("detach0 called\n"); task_t gTask = getTask(env, this_obj); + + // detach from the ptraced process causing it to resume execution + int pid; + kern_return_t k_res; + k_res = pid_for_task(gTask, &pid); + if (k_res != KERN_SUCCESS) { + fprintf(stderr, "detach: pid_for_task(%d) failed (%d)\n", pid, k_res); + } + else { + int res = ptrace(PT_DETACH, pid, 0, 0); + if (res < 0) { + fprintf(stderr, "detach: ptrace(PT_DETACH, %d) failed (%d)\n", pid, res); + } + } + mach_port_deallocate(mach_task_self(), gTask); id symbolicator = getSymbolicator(env, this_obj); if (symbolicator != nil) { CFRelease(symbolicator); }