Source:
<code>public Definitions doCtags(String file) throws IOException, InterruptedException { if (file.length() < 1 || "\n".equals(file)) { return null; } if (ctags != null) { try { int exitValue = ctags.exitValue(); LOGGER.log(Level.WARNING, "Ctags process exited with exit value {0}", exitValue); throw new InterruptedException("ctags process died"); } catch (IllegalThreadStateException exp) { } } else { initialize(); } CtagsReader rdr = new CtagsReader(); rdr.setSplitterSupplier(() -> trySplitSource(file)); rdr.setTabSize(tabSize); Definitions ret; try { ctagsIn.write(file + "\n"); if (Thread.interrupted()) { throw new InterruptedException("write()"); } ctagsIn.flush(); if (Thread.interrupted()) { throw new InterruptedException("flush()"); } int timeout = this.timeout * 1000; Timer timer = null; if (timeout != 0) { timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { LOGGER.log(Level.WARNING, String.format("Terminating ctags process for file '%s' " + "due to timeout %d seconds", file, timeout / 1000)); try { close(); } catch (IOException e) { LOGGER.log(Level.WARNING, "Failed to terminate overly long ctags command"); } } }, timeout); } readTags(rdr); <START> if (timer != null) { <END> timer.cancel(); } ret = rdr.getDefinitions(); } catch (IOException ex) { if (Thread.interrupted()) { throw new InterruptedException("I/O"); } throw ex; } return ret; }</code><technical_language>synchronization, is theoretically readTags() successful log warning message close ctags prematurely, right? I this is edge case timeout waive it</technical_language>

Target:
public Definitions doCtags(String file) throws IOException, InterruptedException { if (file.length() < 1 || "\n".equals(file)) { return null; } if (ctags != null) { try { int exitValue = ctags.exitValue(); LOGGER.log(Level.WARNING, "Ctags process exited with exit value {0}", exitValue); throw new InterruptedException("ctags process died"); } catch (IllegalThreadStateException exp) { } } else { initialize(); } CtagsReader rdr = new CtagsReader(); rdr.setSplitterSupplier(() -> trySplitSource(file)); rdr.setTabSize(tabSize); Definitions ret = null; try { ctagsIn.write(file + "\n"); if (Thread.interrupted()) { throw new InterruptedException("write()"); } ctagsIn.flush(); if (Thread.interrupted()) { throw new InterruptedException("flush()"); } IndexerParallelizer parallelizer = RuntimeEnvironment.getInstance().getIndexerParallelizer(); ExecutorService executor = parallelizer.getCtagsWatcherExecutor(); Future<Definitions> future = executor.submit(() -> { readTags(rdr); return rdr.getDefinitions(); }); try { ret = future.get(getTimeout(), TimeUnit.SECONDS); } catch (ExecutionException ex) { LOGGER.log(Level.WARNING, "execution exception", ex); } catch (TimeoutException ex) { LOGGER.log(Level.WARNING, String.format("Terminating ctags process for file '%s' " + "due to timeout %d seconds", file, getTimeout())); try { close(); } catch (IOException e) { LOGGER.log(Level.WARNING, "Failed to terminate overly long ctags command"); } throw new InterruptedException("ctags timeout"); } } catch (IOException ex) { if (Thread.interrupted()) { throw new InterruptedException("I/O"); } throw ex; } return ret; }