Mercurial > hg > truffle
comparison agent/src/os/bsd/ps_proc.c @ 8058:2394a89e89f4
8008088: SA can hang the VM
Reviewed-by: mgronlun, sla, dholmes
author | rbackman |
---|---|
date | Wed, 13 Feb 2013 09:46:19 +0100 |
parents | f08d439fab8c |
children | 1a04de1aaedb |
comparison
equal
deleted
inserted
replaced
8057:7adae9244bc8 | 8058: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. |
127 ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo)); | 127 ptrace(PT_LWPINFO, lwp_id, linfo, sizeof(struct ptrace_lwpinfo)); |
128 | 128 |
129 return (errno == 0)? true: false; | 129 return (errno == 0)? true: false; |
130 } | 130 } |
131 | 131 |
132 static bool ptrace_continue(pid_t pid, int signal) { | |
133 // pass the signal to the process so we don't swallow it | |
134 if (ptrace(PTRACE_CONT, pid, NULL, signal) < 0) { | |
135 print_debug("ptrace(PTRACE_CONT, ..) failed for %d\n", pid); | |
136 return false; | |
137 } | |
138 return true; | |
139 } | |
140 | |
141 // waits until the ATTACH has stopped the process | |
142 // by signal SIGSTOP | |
143 static bool ptrace_waitpid(pid_t pid) { | |
144 int ret; | |
145 int status; | |
146 do { | |
147 // Wait for debuggee to stop. | |
148 ret = waitpid(pid, &status, 0); | |
149 if (ret >= 0) { | |
150 if (WIFSTOPPED(status)) { | |
151 // Any signal will stop the thread, make sure it is SIGSTOP. Otherwise SIGSTOP | |
152 // will still be pending and delivered when the process is DETACHED and the process | |
153 // will go to sleep. | |
154 if (WSTOPSIG(status) == SIGSTOP) { | |
155 // Debuggee stopped by SIGSTOP. | |
156 return true; | |
157 } | |
158 if (!ptrace_continue(pid, WSTOPSIG(status))) { | |
159 print_error("Failed to correctly attach to VM. VM might HANG! [PTRACE_CONT failed, stopped by %d]\n", WSTOPSIG(status)); | |
160 return false; | |
161 } | |
162 } else { | |
163 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); | |
164 return false; | |
165 } | |
166 } else { | |
167 switch (errno) { | |
168 case EINTR: | |
169 continue; | |
170 break; | |
171 case ECHILD: | |
172 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); | |
173 break; | |
174 case EINVAL: | |
175 print_debug("waitpid() failed. Invalid options argument.\n"); | |
176 break; | |
177 default: | |
178 print_debug("waitpid() failed. Unexpected error %d\n",errno); | |
179 } | |
180 return false; | |
181 } | |
182 } while(true); | |
183 } | |
184 | |
132 // attach to a process/thread specified by "pid" | 185 // attach to a process/thread specified by "pid" |
133 static bool ptrace_attach(pid_t pid) { | 186 static bool ptrace_attach(pid_t pid) { |
134 if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) { | 187 if (ptrace(PT_ATTACH, pid, NULL, 0) < 0) { |
135 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); | 188 print_debug("ptrace(PTRACE_ATTACH, ..) failed for %d\n", pid); |
136 return false; | 189 return false; |
137 } else { | 190 } else { |
138 int ret; | 191 return ptrace_waitpid(pid); |
139 int status; | |
140 do { | |
141 // Wait for debuggee to stop. | |
142 ret = waitpid(pid, &status, 0); | |
143 if (ret >= 0) { | |
144 if (WIFSTOPPED(status)) { | |
145 // Debuggee stopped. | |
146 return true; | |
147 } else { | |
148 print_debug("waitpid(): Child process exited/terminated (status = 0x%x)\n", status); | |
149 return false; | |
150 } | |
151 } else { | |
152 switch (errno) { | |
153 case EINTR: | |
154 continue; | |
155 break; | |
156 case ECHILD: | |
157 print_debug("waitpid() failed. Child process pid (%d) does not exist \n", pid); | |
158 break; | |
159 case EINVAL: | |
160 print_debug("waitpid() failed. Invalid options argument.\n"); | |
161 break; | |
162 default: | |
163 print_debug("waitpid() failed. Unexpected error %d\n",errno); | |
164 } | |
165 return false; | |
166 } | |
167 } while(true); | |
168 } | 192 } |
169 } | 193 } |
170 | 194 |
171 // ------------------------------------------------------- | 195 // ------------------------------------------------------- |
172 // functions for obtaining library information | 196 // functions for obtaining library information |