Author: toad
Date: 2007-09-08 15:49:53 +0000 (Sat, 08 Sep 2007)
New Revision: 15047
Modified:
trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
trunk/freenet/src/freenet/node/TextModeClientInterface.java
trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
trunk/freenet/src/freenet/pluginmanager/PluginManager.java
Log:
Wait up to a limited time for threaded plugins to finish exiting.
Modified: trunk/freenet/src/freenet/clients/http/PproxyToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/PproxyToadlet.java 2007-09-08
15:37:49 UTC (rev 15046)
+++ trunk/freenet/src/freenet/clients/http/PproxyToadlet.java 2007-09-08
15:49:53 UTC (rev 15047)
@@ -23,6 +23,8 @@
public class PproxyToadlet extends Toadlet {
private static final int MAX_PLUGIN_NAME_LENGTH = 1024;
+ /** Maximum time to wait for a threaded plugin to exit */
+ private static final int MAX_THREADED_UNLOAD_WAIT_TIME = 60*1000;
private final Node node;
private final NodeClientCore core;
@@ -124,7 +126,7 @@
ctx.sendReplyHeaders(302, "Found", headers,
null, 0);
return;
}if (request.getPartAsString("unloadconfirm",
MAX_PLUGIN_NAME_LENGTH).length() > 0) {
-
pm.killPlugin(request.getPartAsString("unloadconfirm", MAX_PLUGIN_NAME_LENGTH));
+
pm.killPlugin(request.getPartAsString("unloadconfirm", MAX_PLUGIN_NAME_LENGTH),
MAX_THREADED_UNLOAD_WAIT_TIME);
HTMLNode pageNode =
ctx.getPageMaker().getPageNode(l10n("plugins"), ctx);
HTMLNode contentNode =
ctx.getPageMaker().getContentNode(pageNode);
HTMLNode infobox = contentNode.addChild("div",
"class", "infobox infobox-success");
@@ -164,7 +166,7 @@
sendErrorPage(ctx, 404,
l10n("pluginNotFoundReloadTitle"),
L10n.getString("PluginToadlet.pluginNotFoundReload"));
} else {
-
pm.killPlugin(request.getPartAsString("reload", MAX_PLUGIN_NAME_LENGTH));
+
pm.killPlugin(request.getPartAsString("reload", MAX_PLUGIN_NAME_LENGTH),
MAX_THREADED_UNLOAD_WAIT_TIME);
pm.startPlugin(fn, true);
headers.put("Location", ".");
Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2007-09-08
15:37:49 UTC (rev 15046)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2007-09-08
15:49:53 UTC (rev 15047)
@@ -898,7 +898,7 @@
} else if(uline.startsWith("PLUGLIST")) {
outsb.append(n.pluginManager.dumpPlugins());
} else if(uline.startsWith("PLUGKILL:")) {
-
n.pluginManager.killPlugin(line.substring("PLUGKILL:".length()).trim());
+
n.pluginManager.killPlugin(line.substring("PLUGKILL:".length()).trim(),
60*1000);
} else {
if(uline.length() > 0)
printHeader(out);
Modified: trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
2007-09-08 15:37:49 UTC (rev 15046)
+++ trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
2007-09-08 15:49:53 UTC (rev 15047)
@@ -3,6 +3,7 @@
import java.util.Date;
import java.util.HashSet;
+import freenet.support.Logger;
import freenet.support.StringArray;
public class PluginInfoWrapper {
@@ -20,6 +21,7 @@
private boolean isPortForwardPlugin;
private String filename;
private HashSet toadletLinks=new HashSet();
+ private boolean isExiting = false;
//public String
public PluginInfoWrapper(FredPlugin plug, String filename) {
@@ -86,12 +88,28 @@
* might be sleeping. Then call removePlugin() on it on the manager -
either
* now, if it's threadless, or after it terminates, if it's thread
based.
* @param manager The plugin manager object.
+ * @param maxWaitTime If a plugin is thread-based, we can wait for it to
+ * terminate. Set to -1 if you don't want to wait at all, 0 to wait
forever
+ * or else a value in milliseconds.
**/
- public void stopPlugin(PluginManager manager) {
+ public void stopPlugin(PluginManager manager, int maxWaitTime) {
plug.terminate();
if(thread != null) {
thread.interrupt();
// Will be removed when the thread exits.
+ if(maxWaitTime >= 0) {
+ try {
+ thread.join(maxWaitTime);
+ } catch (InterruptedException e) {
+ Logger.normal(this, "stopPlugin
interrupted while join()ed to terminating plugin thread - maybe one plugin
stopping another???");
+ }
+ if(thread.isAlive()) {
+ String error = "Waited for "+thread+"
for "+plug+" to exit for "+maxWaitTime+"ms, and it is still alive!";
+ Logger.error(this, error);
+ System.err.println(error);
+ // Dump the thread? Would require
post-1.4 features...
+ }
+ }
} else {
// Remove immediately
manager.removePlugin(this);
Modified: trunk/freenet/src/freenet/pluginmanager/PluginManager.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginManager.java 2007-09-08
15:37:49 UTC (rev 15046)
+++ trunk/freenet/src/freenet/pluginmanager/PluginManager.java 2007-09-08
15:49:53 UTC (rev 15047)
@@ -280,7 +280,7 @@
throw new NotFoundPluginHTTPException("Plugin not found!",
"/plugins");
}
- public void killPlugin(String name) {
+ public void killPlugin(String name, int maxWaitTime) {
PluginInfoWrapper pi = null;
boolean found = false;
synchronized (pluginWrappers) {
@@ -291,7 +291,7 @@
}
}
if (found) {
- pi.stopPlugin(this);
+ pi.stopPlugin(this, maxWaitTime);
}
}