Permalink
Browse files

Fixed YaCy proper shutdown triggered by SIGTERM signal.

The main shutdown hook thread was not properly waiting for the main
thread termination which consequently could not properly close resources
and threads. After terminating a running YaCy peer this way (Ctrl+C in
console, or kill <pid> for example), you could see the still existing
DATA/yacy.running file.

Tested with :
 - Debian Jessie openjdk 7 and 8 : regular shutdown, Ctrl+C, kill
command, system restart while yacy is running
 - Windows 10 Oracle JDK 7 and 8 : non regression on regular shutdown
  • Loading branch information...
luccioman committed Dec 28, 2016
1 parent fce701f commit 1df558a6c6c86b96dd87987f7f8b87ad12b901c4
Showing with 19 additions and 8 deletions.
  1. +7 −0 source/net/yacy/search/Switchboard.java
  2. +12 −8 source/net/yacy/yacy.java
@@ -1872,6 +1872,10 @@ public boolean cleanProfiles() throws InterruptedException {
public synchronized void close() {
this.log.config("SWITCHBOARD SHUTDOWN STEP 1: sending termination signal to managed threads:");
/* Print also to the standard output : when this method is triggered by the shutdown hook thread, the LogManager is likely to have
* been concurrently reset by its own shutdown hook thread */
System.out.println("SWITCHBOARD Performing shutdown steps...");
MemoryTracker.stopSystemProfiling();
terminateAllThreads(true);
net.yacy.gui.framework.Switchboard.shutdown();
@@ -1915,6 +1919,9 @@ public synchronized void close() {
ConcurrentLog.logException(e);
}
this.log.config("SWITCHBOARD SHUTDOWN TERMINATED");
/* Print also to the standard output : when this method is triggered by the shutdown hook thread, the LogManager is likely to have
* been concurrently reset by its own shutdown hook thread */
System.out.println("SWITCHBOARD Shutdown steps terminated.");
}
/**
@@ -41,6 +41,7 @@
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import com.google.common.io.Files;
@@ -50,7 +51,6 @@
import net.yacy.cora.order.Digest;
import net.yacy.cora.protocol.ClientIdentification;
import net.yacy.cora.protocol.ConnectionInfo;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.cora.protocol.TimeoutRequest;
import net.yacy.cora.protocol.http.HTTPClient;
import net.yacy.cora.sorting.Array;
@@ -365,7 +365,7 @@ public void run() {
// registering shutdown hook
ConcurrentLog.config("STARTUP", "Registering Shutdown Hook");
final Runtime run = Runtime.getRuntime();
run.addShutdownHook(new shutdownHookThread(Thread.currentThread(), sb));
run.addShutdownHook(new shutdownHookThread(sb, shutdownSemaphore));
// save information about available memory after all initializations
//try {
@@ -784,29 +784,33 @@ public static void main(String args[]) {
*/
class shutdownHookThread extends Thread {
private final Switchboard sb;
private final Thread mainThread;
private final Semaphore shutdownSemaphore;
public shutdownHookThread(final Thread mainThread, final Switchboard sb) {
public shutdownHookThread(final Switchboard sb, final Semaphore shutdownSemaphore) {
super("yacy.shutdownHookThread");
this.sb = sb;
this.mainThread = mainThread;
this.shutdownSemaphore = shutdownSemaphore;
}
@Override
public void run() {
try {
if (!this.sb.isTerminated()) {
ConcurrentLog.config("SHUTDOWN","Shutdown via shutdown hook.");
/* Print also to the standard output, as the LogManager is likely to have
* been concurrently reset by its own shutdown hook thread */
System.out.println("SHUTDOWN Starting shutdown via shutdown hook.");
// sending the yacy main thread a shutdown signal
ConcurrentLog.fine("SHUTDOWN","Signaling shutdown to the switchboard.");
this.sb.terminate("shutdown hook");
// waiting for the yacy thread to finish execution
ConcurrentLog.fine("SHUTDOWN","Waiting for main thread to finish.");
if (this.mainThread.isAlive() && !this.sb.isTerminated()) {
this.mainThread.join();
}
/* Main thread will release the shutdownSemaphore once completely terminated.
* We do not wait indefinitely as the application is supposed here to quickly terminate */
this.shutdownSemaphore.tryAcquire(30, TimeUnit.SECONDS);
}
} catch (final Exception e) {
ConcurrentLog.severe("SHUTDOWN","Unexpected error. " + e.getClass().getName(),e);

0 comments on commit 1df558a

Please sign in to comment.