Author: xor
Date: 2007-12-29 09:36:50 +0000 (Sat, 29 Dec 2007)
New Revision: 16838
Modified:
trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
trunk/freenet/src/freenet/node/Node.java
Log:
Add a workaround for a bug in GCJ InputStreamReader.refill(). This bug
prevented many freesites from loading, the following exception was shown [it is
commented in HTMLFilter.java]:
Internal error: please report
java.io.CharConversionException
at java.io.InputStreamReader.refill(libgcj.so.70)
at java.io.InputStreamReader.read(libgcj.so.70)
at java.io.BufferedReader.fill(libgcj.so.70)
at java.io.BufferedReader.read(libgcj.so.70)
at
freenet.clients.http.filter.HTMLFilter$HTMLParseContext.run(HTMLFilter.java:163)
at freenet.clients.http.filter.HTMLFilter.getCharset(HTMLFilter.java:103)
at
freenet.clients.http.filter.ContentFilter.detectCharset(ContentFilter.java:222)
at freenet.clients.http.filter.ContentFilter.filter(ContentFilter.java:169)
at freenet.clients.http.FProxyToadlet.handleDownload(FProxyToadlet.java:105)
at freenet.clients.http.FProxyToadlet.handleGet(FProxyToadlet.java:385)
at
freenet.clients.http.ToadletContextImpl.handle(ToadletContextImpl.java:322)
at
freenet.clients.http.SimpleToadletServer$SocketHandler.run(SimpleToadletServer.java:459)
at freenet.support.PooledExecutor$MyThread.run(PooledExecutor.java:129)
Modified: trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
2007-12-29 02:36:16 UTC (rev 16837)
+++ trunk/freenet/src/freenet/clients/http/filter/HTMLFilter.java
2007-12-29 09:36:50 UTC (rev 16838)
@@ -160,7 +160,24 @@
mode = INTEXT;
while (true) {
- int x = r.read();
+ int x;
+
+ try {
+ x = r.read();
+ }
+ /**
+ * libgcj up to at least 4.2.2 has a bug:
InputStreamReader.refill() throws this exception when
BufferedInputReader.refill() returns false for EOF. See:
+ * line 299 at InputStreamReader.java (in
refill()):
http://www.koders.com/java/fidD8F7E2EB1E4C22DA90EBE0130306AE30F876AB00.aspx?s=refill#L279
+ * line 355 at BufferedInputStream.java (in
refill()):
http://www.koders.com/java/fid1949641524FAC0083432D79793F554CD85F46759.aspx?s=refill#L355
+ * TODO: remove this when the gcj bug is fixed
and the affected gcj versions are outdated.
+ */
+ catch(java.io.CharConversionException cce) {
+
if(freenet.node.Node.checkForGCJCharConversionBug()) /* only ignore the
exception on affected libgcj */
+ x = -1;
+ else
+ throw cce;
+ }
+
if (x == -1) {
switch (mode) {
case INTEXT :
Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java 2007-12-29 02:36:16 UTC (rev
16837)
+++ trunk/freenet/src/freenet/node/Node.java 2007-12-29 09:36:50 UTC (rev
16838)
@@ -1490,7 +1490,13 @@
if(testnetHandler != null)
testnetHandler.start();
- checkForEvilJVMBug();
+ /* TODO: Make sure that this is called BEFORE any instances of
HTTPFilter are created.
+ * HTTPFilter uses checkForGCJCharConversionBug() which returns
the value of the static
+ * variable jvmHasGCJCharConversionBug - and this is
initialized in the following function.
+ * If this is not possible then create a separate function to
check for the GCJ bug and
+ * call this function earlier.
+ */
+ checkForEvilJVMBugs();
// TODO: implement a "required" version if needed
if(!nodeUpdater.isEnabled() &&
(NodeStarter.RECOMMENDED_EXT_BUILD_NUMBER > NodeStarter.extBuildNumber))
@@ -1518,7 +1524,9 @@
hasStarted = true;
}
- private void checkForEvilJVMBug() {
+ private static boolean jvmHasGCJCharConversionBug=false;
+
+ private void checkForEvilJVMBugs() {
// Now check whether we are likely to get the EvilJVMBug.
// If we are running a Sun or Blackdown JVM, on Linux, and
LD_ASSUME_KERNEL is not set, then we are.
@@ -1594,6 +1602,20 @@
} else if (jvmVendor.startsWith("Apple ") ||
jvmVendor.startsWith("\"Apple ")) {
//Note that Sun does not produce VMs for the Macintosh
operating system, dont ask the user to find one...
} else {
+ if(jvmVendor.startsWith("Free Software Foundation")) {
+ try {
+ jvmVersion =
System.getProperty("java.vm.version").split(" ")[0].replace(".","");
+ int jvmVersionInt =
Integer.parseInt(jvmVersion);
+
+ if(jvmVersionInt <= 422 &&
jvmVersionInt >= 100) // make sure that no bogus values cause true
+ jvmHasGCJCharConversionBug=true;
+ }
+
+ catch(Throwable t) {
+ Logger.error(this, "GCJ version check
is broken!", t);
+ }
+ }
+
clientCore.alerts.register(new SimpleUserAlert(true,
l10n("notUsingSunVMTitle"), l10n("notUsingSunVM", new String[] { "vendor",
"version" }, new String[] { jvmVendor, jvmVersion }), UserAlert.WARNING));
}
@@ -1603,6 +1625,10 @@
}
+ public static boolean checkForGCJCharConversionBug() {
+ return jvmHasGCJCharConversionBug; // should be initialized on
early startup
+ }
+
private String l10n(String key) {
return L10n.getString("Node."+key);
}