agent/src/os/bsd/ps_proc.c

changeset 4599
2394a89e89f4
parent 3156
f08d439fab8c
child 6031
1a04de1aaedb
     1.1 --- a/agent/src/os/bsd/ps_proc.c	Wed Feb 13 11:23:46 2013 +0100
     1.2 +++ b/agent/src/os/bsd/ps_proc.c	Wed Feb 13 09:46:19 2013 +0100
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -129,42 +129,66 @@
    1.11    return (errno == 0)? true: false;
    1.12  }
    1.13  
    1.14 +static bool ptrace_continue(pid_t pid, int signal) {
    1.15 +  // pass the signal to the process so we don't swallow it
    1.16 +  if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) {
    1.17 +    print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
    1.18 +    return false;
    1.19 +  }
    1.20 +  return true;
    1.21 +}
    1.22 +
    1.23 +// waits until the ATTACH has stopped the process
    1.24 +// by signal SIGSTOP
    1.25 +static bool ptrace_waitpid(pid_t pid) {
    1.26 +  int ret;
    1.27 +  int status;
    1.28 +  do {
    1.29 +    // Wait for debuggee to stop.
    1.30 +    ret = waitpid(pid, &status, 0);
    1.31 +    if (ret >= 0) {
    1.32 +      if (WIFSTOPPED(status)) {
    1.33 +        // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
    1.34 +        // will still be pending and delivered when the process is DETACHED and the process
    1.35 +        // will go to sleep.
    1.36 +        if (WSTOPSIG(status) == SIGSTOP) {
    1.37 +          // Debuggee stopped by SIGSTOP.
    1.38 +          return true;
    1.39 +        }
    1.40 +        if (!ptrace_continue(pid, WSTOPSIG(status))) {
    1.41 +          print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
    1.42 +          return false;
    1.43 +        }
    1.44 +      } else {
    1.45 +        print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
    1.46 +        return false;
    1.47 +      }
    1.48 +    } else {
    1.49 +      switch (errno) {
    1.50 +        case EINTR:
    1.51 +          continue;
    1.52 +          break;
    1.53 +        case ECHILD:
    1.54 +          print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
    1.55 +          break;
    1.56 +        case EINVAL:
    1.57 +          print_debug("waitpid() failed. Invalid options argument.\n");
    1.58 +          break;
    1.59 +        default:
    1.60 +          print_debug("waitpid() failed. Unexpected error %d\n",errno);
    1.61 +      }
    1.62 +      return false;
    1.63 +    }
    1.64 +  } while(true);
    1.65 +}
    1.66 +
    1.67  // attach to a process/thread specified by "pid"
    1.68  static bool ptrace_attach(pid_t pid) {
    1.69    if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) {
    1.70      print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
    1.71      return false;
    1.72    } else {
    1.73 -    int ret;
    1.74 -    int status;
    1.75 -    do {
    1.76 -      // Wait for debuggee to stop.
    1.77 -      ret = waitpid(pid, &status, 0);
    1.78 -      if (ret >= 0) {
    1.79 -        if (WIFSTOPPED(status)) {
    1.80 -          // Debuggee stopped.
    1.81 -          return true;
    1.82 -        } else {
    1.83 -          print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
    1.84 -          return false;
    1.85 -        }
    1.86 -      } else {
    1.87 -        switch (errno) {
    1.88 -          case EINTR:
    1.89 -            continue;
    1.90 -            break;
    1.91 -          case ECHILD:
    1.92 -            print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
    1.93 -            break;
    1.94 -          case EINVAL:
    1.95 -            print_debug("waitpid() failed. Invalid options argument.\n");
    1.96 -            break;
    1.97 -          default:
    1.98 -            print_debug("waitpid() failed. Unexpected error %d\n",errno);
    1.99 -        }
   1.100 -        return false;
   1.101 -      }
   1.102 -    } while(true);
   1.103 +    return ptrace_waitpid(pid);
   1.104    }
   1.105  }
   1.106  

mercurial