133 # 3) ^main[89] main[89] ... 134 # 135 # This occurs if the next cmd is one that causes no jdb output, e.g., 136 # 'trace methods'. 137 # 138 # 4) ^main[89] [main[89]] .... > @ 139 # 140 # jdb prints a > as a prompt after something like a cont. 141 # Thus, even though the above is the last 'line' in the file, it 142 # isn't the next prompt we are waiting for after the cont completes. 143 # HOWEVER, sometimes we see this for a cont command: 144 # 145 # ^main[89] $ 146 # <lines output for hitting a bkpt> 147 # 148 # 5) ^main[89] > @ 149 # 150 # i.e., the > prompt comes out AFTER the prompt we we need to wait for. 151 */ 152 // compile regexp once 153 private final String promptPattern = "[a-zA-Z0-9_-][a-zA-Z0-9_-]*\\[[1-9][0-9]*\\] [ >]*$"; 154 private final Pattern promptRegexp = Pattern.compile(promptPattern); 155 public List<String> waitForPrompt(int lines, boolean allowExit) { 156 return waitForPrompt(lines, allowExit, promptRegexp); 157 } 158 159 // jdb prompt when debuggee is not started and is not suspended after breakpoint 160 private static final String SIMPLE_PROMPT = "> "; 161 public List<String> waitForSimplePrompt(int lines, boolean allowExit) { 162 return waitForPrompt(lines, allowExit, Pattern.compile(SIMPLE_PROMPT)); 163 } 164 165 private List<String> waitForPrompt(int lines, boolean allowExit, Pattern promptRegexp) { 166 long startTime = System.currentTimeMillis(); 167 while (System.currentTimeMillis() - startTime < timeout) { 168 try { 169 Thread.sleep(sleepTime); 170 } catch (InterruptedException e) { 171 // ignore 172 } 173 synchronized (outputHandler) { 174 if (!outputHandler.updated()) { 175 try { 176 outputHandler.wait(sleepTime); 177 } catch (InterruptedException e) { 178 // ignore 179 } 180 } else { 181 // if something appeared in the jdb output, reset the timeout 182 startTime = System.currentTimeMillis(); 183 } 184 } 185 List<String> reply = outputHandler.get(); 186 for (String line: reply.subList(Math.max(0, reply.size() - lines), reply.size())) { 187 if (promptRegexp.matcher(line).find()) { 188 logJdb(reply); 189 return outputHandler.reset(); 190 } 191 } 192 if (!jdb.isAlive()) { 193 // ensure we get the whole output 194 reply = outputHandler.reset(); 195 logJdb(reply); 196 if (!allowExit) { 197 throw new RuntimeException("waitForPrompt timed out after " + (timeout/1000) 198 + " seconds, looking for '" + promptPattern + "', in " + lines + " lines"); 199 } 200 return reply; 201 } 202 } 203 // timeout 204 logJdb(outputHandler.get()); 205 throw new RuntimeException("waitForPrompt timed out after " + (timeout/1000) 206 + " seconds, looking for '" + promptPattern + "', in " + lines + " lines"); 207 } 208 209 public List<String> command(JdbCommand cmd) { 210 if (!jdb.isAlive()) { 211 if (cmd.allowExit) { 212 // return remaining output 213 return outputHandler.reset(); 214 } 215 throw new RuntimeException("Attempt to send command '" + cmd.cmd + "' to terminated jdb"); 216 } 217 218 log("> " + cmd.cmd); 219 220 inputWriter.println(cmd.cmd); 221 222 if (inputWriter.checkError()) { 223 throw new RuntimeException("Unexpected IO error while writing command '" + cmd.cmd + "' to jdb stdin stream"); 224 } 225 226 return waitForPrompt(1, cmd.allowExit); 227 } 228 229 public List<String> command(String cmd) { 230 return command(new JdbCommand(cmd)); 231 } 232 233 // sends "cont" command up to maxTimes until debuggee exit 234 public void contToExit(int maxTimes) { 235 boolean exited = false; 236 JdbCommand cont = JdbCommand.cont().allowExit(); 237 for (int i = 0; i < maxTimes && jdb.isAlive(); i++) { 238 String reply = command(cont).stream().collect(Collectors.joining(lineSeparator)); 239 if (reply.contains(APPLICATION_EXIT)) { 240 exited = true; 241 break; 242 } 243 } 244 if (!exited && jdb.isAlive()) { 245 throw new RuntimeException("Debuggee did not exit after " + maxTimes + " <cont> commands"); 246 } | 133 # 3) ^main[89] main[89] ... 134 # 135 # This occurs if the next cmd is one that causes no jdb output, e.g., 136 # 'trace methods'. 137 # 138 # 4) ^main[89] [main[89]] .... > @ 139 # 140 # jdb prints a > as a prompt after something like a cont. 141 # Thus, even though the above is the last 'line' in the file, it 142 # isn't the next prompt we are waiting for after the cont completes. 143 # HOWEVER, sometimes we see this for a cont command: 144 # 145 # ^main[89] $ 146 # <lines output for hitting a bkpt> 147 # 148 # 5) ^main[89] > @ 149 # 150 # i.e., the > prompt comes out AFTER the prompt we we need to wait for. 151 */ 152 // compile regexp once 153 private final static String promptPattern = "[a-zA-Z0-9_-][a-zA-Z0-9_-]*\\[[1-9][0-9]*\\] [ >]*$"; 154 final static Pattern PROMPT_REGEXP = Pattern.compile(promptPattern); 155 156 public List<String> waitForPrompt(int lines, boolean allowExit) { 157 return waitForPrompt(lines, allowExit, PROMPT_REGEXP); 158 } 159 160 // jdb prompt when debuggee is not started and is not suspended after breakpoint 161 private static final String SIMPLE_PROMPT = "> "; 162 public List<String> waitForSimplePrompt(int lines, boolean allowExit) { 163 return waitForPrompt(lines, allowExit, Pattern.compile(SIMPLE_PROMPT)); 164 } 165 166 private List<String> waitForPrompt(int lines, boolean allowExit, Pattern promptRegexp) { 167 long startTime = System.currentTimeMillis(); 168 while (System.currentTimeMillis() - startTime < timeout) { 169 try { 170 Thread.sleep(sleepTime); 171 } catch (InterruptedException e) { 172 // ignore 173 } 174 synchronized (outputHandler) { 175 if (!outputHandler.updated()) { 176 try { 177 outputHandler.wait(sleepTime); 178 } catch (InterruptedException e) { 179 // ignore 180 } 181 } else { 182 // if something appeared in the jdb output, reset the timeout 183 startTime = System.currentTimeMillis(); 184 } 185 } 186 List<String> reply = outputHandler.get(); 187 if ((promptRegexp.flags() & Pattern.MULTILINE) > 0) { 188 String replyString = reply.stream().collect(Collectors.joining(lineSeparator)); 189 if (promptRegexp.matcher(replyString).find()) { 190 logJdb(reply); 191 return outputHandler.reset(); 192 } 193 } else { 194 for (String line : reply.subList(Math.max(0, reply.size() - lines), reply.size())) { 195 if (promptRegexp.matcher(line).find()) { 196 logJdb(reply); 197 return outputHandler.reset(); 198 } 199 } 200 } 201 if (!jdb.isAlive()) { 202 // ensure we get the whole output 203 reply = outputHandler.reset(); 204 logJdb(reply); 205 if (!allowExit) { 206 throw new RuntimeException("waitForPrompt timed out after " + (timeout/1000) 207 + " seconds, looking for '" + promptRegexp.pattern() + "', in " + lines + " lines"); 208 } 209 return reply; 210 } 211 } 212 // timeout 213 logJdb(outputHandler.get()); 214 throw new RuntimeException("waitForPrompt timed out after " + (timeout/1000) 215 + " seconds, looking for '" + promptRegexp.pattern() + "', in " + lines + " lines"); 216 } 217 218 public List<String> command(JdbCommand cmd) { 219 if (!jdb.isAlive()) { 220 if (cmd.allowExit) { 221 // return remaining output 222 return outputHandler.reset(); 223 } 224 throw new RuntimeException("Attempt to send command '" + cmd.cmd + "' to terminated jdb"); 225 } 226 227 log("> " + cmd.cmd); 228 229 inputWriter.println(cmd.cmd); 230 231 if (inputWriter.checkError()) { 232 throw new RuntimeException("Unexpected IO error while writing command '" + cmd.cmd + "' to jdb stdin stream"); 233 } 234 235 return waitForPrompt(1, cmd.allowExit, cmd.waitForPattern); 236 } 237 238 public List<String> command(String cmd) { 239 return command(new JdbCommand(cmd)); 240 } 241 242 // sends "cont" command up to maxTimes until debuggee exit 243 public void contToExit(int maxTimes) { 244 boolean exited = false; 245 JdbCommand cont = JdbCommand.cont().allowExit(); 246 for (int i = 0; i < maxTimes && jdb.isAlive(); i++) { 247 String reply = command(cont).stream().collect(Collectors.joining(lineSeparator)); 248 if (reply.contains(APPLICATION_EXIT)) { 249 exited = true; 250 break; 251 } 252 } 253 if (!exited && jdb.isAlive()) { 254 throw new RuntimeException("Debuggee did not exit after " + maxTimes + " <cont> commands"); 255 } |