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);
}