From c8074bdbf351e9ca0db904b6ceb4939b9804673e Mon Sep 17 00:00:00 2001 From: gojomo Date: Mon, 15 Nov 2010 22:26:36 +0000 Subject: [PATCH] Improve ability to force-terminate crawls * RecordingInputStream.java check for interrupt on each socket-timeout * CrawlController.java on second requestCrawlStop, interrupt threads via ToePool.cleanup * ToePool.java adjust for new earlier/repeated cleanup * ToeThread.java better warnings/recovery on forced-interrupts --- .../java/org/archive/io/RecordingInputStream.java | 4 ++++ .../archive/crawler/framework/CrawlController.java | 4 ++++ .../java/org/archive/crawler/framework/ToePool.java | 5 ++++- .../org/archive/crawler/framework/ToeThread.java | 12 +++++++++++- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/commons/src/main/java/org/archive/io/RecordingInputStream.java b/commons/src/main/java/org/archive/io/RecordingInputStream.java index 8e0202f4..9f3991cc 100644 --- a/commons/src/main/java/org/archive/io/RecordingInputStream.java +++ b/commons/src/main/java/org/archive/io/RecordingInputStream.java @@ -219,6 +219,10 @@ public class RecordingInputStream if (logger.isLoggable(Level.FINE)) { logger.log(Level.FINE, "socket timeout", e); } + // check for interrupt + if (Thread.interrupted()) { + throw new InterruptedException("Interrupted during IO"); + } // check for overall timeout recordingOutputStream.checkLimits(); } catch (SocketException se) { diff --git a/engine/src/main/java/org/archive/crawler/framework/CrawlController.java b/engine/src/main/java/org/archive/crawler/framework/CrawlController.java index f33abbc9..d0f27349 100644 --- a/engine/src/main/java/org/archive/crawler/framework/CrawlController.java +++ b/engine/src/main/java/org/archive/crawler/framework/CrawlController.java @@ -398,6 +398,10 @@ implements Serializable, * Operator requested for crawl to stop. */ public synchronized void requestCrawlStop() { + if(state == State.STOPPING) { + // second stop request; nudge the threads with interrupts + getToePool().cleanup(); + } requestCrawlStop(CrawlStatus.ABORTED); } diff --git a/engine/src/main/java/org/archive/crawler/framework/ToePool.java b/engine/src/main/java/org/archive/crawler/framework/ToePool.java index e068ab15..990f0f11 100644 --- a/engine/src/main/java/org/archive/crawler/framework/ToePool.java +++ b/engine/src/main/java/org/archive/crawler/framework/ToePool.java @@ -70,7 +70,7 @@ public class ToePool extends ThreadGroup implements MultiReporter { toe.interrupt(); } } - this.controller = null; +// this.controller = null; } /** @@ -297,6 +297,9 @@ public class ToePool extends ThreadGroup implements MultiReporter { w.print(" threads: "); TreeSet> sortedSteps = (TreeSet>) map.get("steps"); + if(sortedSteps.size()==0) { + return; + } w.print(Histotable.entryString(sortedSteps.first())); if(sortedSteps.size()>1) { Iterator> iter = sortedSteps.iterator(); diff --git a/engine/src/main/java/org/archive/crawler/framework/ToeThread.java b/engine/src/main/java/org/archive/crawler/framework/ToeThread.java index a7414d92..b079a200 100644 --- a/engine/src/main/java/org/archive/crawler/framework/ToeThread.java +++ b/engine/src/main/java/org/archive/crawler/framework/ToeThread.java @@ -162,6 +162,13 @@ implements MultiReporter, ProgressStatisticsReporter, recoverableProblem(ae); } catch (RuntimeException e) { recoverableProblem(e); + } catch (InterruptedException e) { + if(currentCuri!=null) { + recoverableProblem(e); + Thread.interrupted(); // clear interrupt status + } else { + throw e; + } } catch (StackOverflowError err) { recoverableProblem(err); } catch (Error err) { @@ -187,6 +194,9 @@ implements MultiReporter, ProgressStatisticsReporter, } } } catch (InterruptedException e) { + if(currentCuri!=null){ + logger.log(Level.SEVERE,"Interrupt leaving unfinished CrawlURI "+getName()+" - job may hang",e); + } // thread interrupted, ok to end logger.log(Level.FINE,this.getName()+ " ended with Interruption"); } catch (Exception e) { @@ -288,7 +298,7 @@ implements MultiReporter, ProgressStatisticsReporter, private void recoverableProblem(Throwable e) { Object previousStep = step; setStep(Step.HANDLING_RUNTIME_EXCEPTION, null); - e.printStackTrace(System.err); + //e.printStackTrace(System.err); currentCuri.setFetchStatus(S_RUNTIME_EXCEPTION); // store exception temporarily for logging currentCuri.getAnnotations().add("err="+e.getClass().getName());