agent/src/os/linux/ps_proc.c

changeset 4599
2394a89e89f4
parent 2384
0a8e0d4345b3
child 5797
f2512d89ad0c
equal deleted inserted replaced
4598:7adae9244bc8 4599:2394a89e89f4
1 /* 1 /*
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
23 */ 23 */
24 24
25 #include <stdio.h> 25 #include <stdio.h>
26 #include <stdlib.h> 26 #include <stdlib.h>
27 #include <string.h> 27 #include <string.h>
28 #include <signal.h>
28 #include <errno.h> 29 #include <errno.h>
29 #include <sys/ptrace.h> 30 #include <sys/ptrace.h>
30 #include "libproc_impl.h" 31 #include "libproc_impl.h"
31 32
32 #if defined(x86_64) && !defined(amd64) 33 #if defined(x86_64) && !defined(amd64)
140 return false; 141 return false;
141 #endif 142 #endif
142 143
143 } 144 }
144 145
146 static bool ptrace_continue(pid_t pid, int signal) {
147 // pass the signal to the process so we don't swallow it
148 if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) {
149 print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid);
150 return false;
151 }
152 return true;
153 }
154
155 // waits until the ATTACH has stopped the process
156 // by signal SIGSTOP
157 static bool ptrace_waitpid(pid_t pid) {
158 int ret;
159 int status;
160 while (true) {
161 // Wait for debuggee to stop.
162 ret = waitpid(pid, &status, 0);
163 if (ret == -1 && errno == ECHILD) {
164 // try cloned process.
165 ret = waitpid(pid, &status, __WALL);
166 }
167 if (ret >= 0) {
168 if (WIFSTOPPED(status)) {
169 // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP
170 // will still be pending and delivered when the process is DETACHED and the process
171 // will go to sleep.
172 if (WSTOPSIG(status) == SIGSTOP) {
173 // Debuggee stopped by SIGSTOP.
174 return true;
175 }
176 if (!ptrace_continue(pid, WSTOPSIG(status))) {
177 print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status));
178 return false;
179 }
180 } else {
181 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
182 return false;
183 }
184 } else {
185 switch (errno) {
186 case EINTR:
187 continue;
188 break;
189 case ECHILD:
190 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
191 break;
192 case EINVAL:
193 print_debug("waitpid() failed. Invalid options argument.\n");
194 break;
195 default:
196 print_debug("waitpid() failed. Unexpected error %d\n",errno);
197 break;
198 }
199 return false;
200 }
201 }
202 }
203
145 // attach to a process/thread specified by "pid" 204 // attach to a process/thread specified by "pid"
146 static bool ptrace_attach(pid_t pid) { 205 static bool ptrace_attach(pid_t pid) {
147 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { 206 if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
148 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); 207 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid);
149 return false; 208 return false;
150 } else { 209 } else {
151 int ret; 210 return ptrace_waitpid(pid);
152 int status;
153 do {
154 // Wait for debuggee to stop.
155 ret = waitpid(pid, &status, 0);
156 if (ret == -1 && errno == ECHILD) {
157 // try cloned process.
158 ret = waitpid(pid, &status, __WALL);
159 }
160 if (ret >= 0) {
161 if (WIFSTOPPED(status)) {
162 // Debuggee stopped.
163 return true;
164 } else {
165 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status);
166 return false;
167 }
168 } else {
169 switch (errno) {
170 case EINTR:
171 continue;
172 break;
173 case ECHILD:
174 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid);
175 break;
176 case EINVAL:
177 print_debug("waitpid() failed. Invalid options argument.\n");
178 break;
179 default:
180 print_debug("waitpid() failed. Unexpected error %d\n",errno);
181 }
182 return false;
183 }
184 } while(true);
185 } 211 }
186 } 212 }
187 213
188 // ------------------------------------------------------- 214 // -------------------------------------------------------
189 // functions for obtaining library information 215 // functions for obtaining library information

mercurial