32
32
import java .io .StringReader ;
33
33
import java .util .ArrayList ;
34
34
import java .util .List ;
35
- import java .util .concurrent .ScheduledFuture ;
36
- import java .util .concurrent .ScheduledThreadPoolExecutor ;
37
- import java .util .concurrent .TimeUnit ;
38
35
import java .util .logging .Level ;
39
36
import java .util .logging .Logger ;
40
37
import org .opensolaris .opengrok .configuration .RuntimeEnvironment ;
49
46
public class Ctags {
50
47
51
48
private static final Logger LOGGER = LoggerFactory .getLogger (Ctags .class );
52
- private static final long SIGNALWAIT_MS = 5000 ;
53
49
54
- /**
55
- * Wait up to 90 seconds for ctags to run, which is a very long time for a
56
- * single run but is really intended for detecting blocked ctags processes
57
- * as happened with @tuxillo's testing of
58
- * <a href="https://github.com/oracle/opengrok/pull/1936">
59
- * Feature/deferred_ops</a>.
60
- */
61
- private static final long CTAGSWAIT_S = 90 ;
62
-
63
- private final ScheduledThreadPoolExecutor schedExecutor ;
64
- private final CtagsBuffer buffer = new CtagsBuffer ();
65
- private final Object syncRoot = new Object ();
66
50
private volatile boolean closing ;
67
- private volatile boolean signalled ;
68
51
private Process ctags ;
69
52
private Thread errThread ;
70
- private Thread outThread ;
71
53
private OutputStreamWriter ctagsIn ;
72
54
private BufferedReader ctagsOut ;
73
55
private static final String CTAGS_FILTER_TERMINATOR = "__ctags_done_with_file__" ;
@@ -78,27 +60,13 @@ public class Ctags {
78
60
private boolean junit_testing = false ;
79
61
80
62
/**
81
- * Initializes an instance using the specified, required executor which
82
- * will be used to track ctags timeouts to avoid blockages.
83
- * <p>(The {@code schedExecutor} is not owned by {@link Ctags}.)
84
- * @param schedExecutor required, defined instance
85
- */
86
- public Ctags (ScheduledThreadPoolExecutor schedExecutor ) {
87
- if (schedExecutor == null ) {
88
- throw new IllegalArgumentException ("`schedExecutor' is null" );
89
- }
90
- this .schedExecutor = schedExecutor ;
91
- }
92
-
93
- /**
94
- * Gets a value indicating if a subprocess of ctags was started and either:
95
- * 1) it is not alive; or 2) any necessary supporting thread is not alive.
63
+ * Gets a value indicating if a subprocess of ctags was started and it is
64
+ * not alive.
96
65
* @return {@code true} if the instance should be considered closed and no
97
66
* longer usable.
98
67
*/
99
68
public boolean isClosed () {
100
- return ctags != null && (!ctags .isAlive () || outThread == null ||
101
- !outThread .isAlive ());
69
+ return ctags != null && !ctags .isAlive ();
102
70
}
103
71
104
72
public String getBinary () {
@@ -354,12 +322,6 @@ public void run() {
354
322
});
355
323
errThread .setDaemon (true );
356
324
errThread .start ();
357
-
358
- if (outThread == null || !outThread .isAlive ()) {
359
- outThread = new Thread (() -> outThreadStart ());
360
- outThread .setDaemon (true );
361
- outThread .start ();
362
- }
363
325
}
364
326
365
327
public Definitions doCtags (String file ) throws IOException ,
@@ -382,44 +344,24 @@ public Definitions doCtags(String file) throws IOException,
382
344
initialize ();
383
345
}
384
346
385
- synchronized (syncRoot ) {
386
- signalled = true ;
387
- syncRoot .notify ();
388
- }
389
-
390
- Thread clientThread = Thread .currentThread ();
391
- ScheduledFuture futureTimeout = schedExecutor .schedule (() -> {
392
- LOGGER .log (Level .FINE , "Ctags futureTimeout executing re t{0}." ,
393
- clientThread .getId ());
394
- clientThread .interrupt ();
395
- outThread .interrupt ();
396
- ctags .destroyForcibly ();
397
- LOGGER .log (Level .FINE , "Ctags futureTimeout executed." );
398
- }, CTAGSWAIT_S , TimeUnit .SECONDS );
399
-
347
+ CtagsReader rdr = new CtagsReader ();
400
348
Definitions ret ;
401
349
try {
402
350
ctagsIn .write (file );
403
351
if (Thread .interrupted ()) throw new InterruptedException ("write()" );
404
352
ctagsIn .flush ();
405
353
if (Thread .interrupted ()) throw new InterruptedException ("flush()" );
406
- ret = buffer .take ();
354
+ readTags (rdr );
355
+ ret = rdr .getDefinitions ();
407
356
} catch (IOException ex ) {
408
357
/*
409
358
* In case the ctags process had to be destroyed, possibly pre-empt
410
359
* the IOException with an InterruptedException.
411
360
*/
412
361
if (Thread .interrupted ()) throw new InterruptedException ("I/O" );
413
362
throw ex ;
414
- } finally {
415
- futureTimeout .cancel (false );
416
363
}
417
364
418
- /*
419
- * If the timeout could not be canceled in time, then act as if no
420
- * results were obtained.
421
- */
422
- if (Thread .interrupted ()) throw new InterruptedException ("late" );
423
365
return ret ;
424
366
}
425
367
@@ -518,45 +460,4 @@ private void readTags(CtagsReader reader) throws InterruptedException {
518
460
}
519
461
LOGGER .severe ("CTag reader cycle was interrupted!" );
520
462
}
521
-
522
- private void outThreadStart () {
523
- while (!closing ) {
524
- synchronized (syncRoot ) {
525
- while (!signalled && !closing ) {
526
- try {
527
- syncRoot .wait (SIGNALWAIT_MS );
528
- } catch (InterruptedException e ) {
529
- LOGGER .log (Level .WARNING ,
530
- "Ctags outThread unexpectedly interrupted--{0}" ,
531
- e .getMessage ());
532
- /*
533
- * Terminating this thread will cause this Ctags
534
- * instance, which appears to be blocked, to be
535
- * reported as closed by isClosed().
536
- */
537
- return ;
538
- }
539
- }
540
- signalled = false ;
541
- }
542
- if (closing ) return ;
543
-
544
- CtagsReader rdr = new CtagsReader ();
545
- try {
546
- readTags (rdr );
547
- Definitions defs = rdr .getDefinitions ();
548
- buffer .put (defs );
549
- } catch (InterruptedException ex ) {
550
- LOGGER .log (Level .WARNING ,
551
- "Ctags outThread unexpectedly interrupted--{0}" ,
552
- ex .getMessage ());
553
- /*
554
- * Terminating this thread will cause this Ctags instance,
555
- * which appears to be blocked, to be reported as closed by
556
- * isClosed().
557
- */
558
- return ;
559
- }
560
- }
561
- }
562
463
}
0 commit comments