BUGFIX: streaming lib blocking on a write() will now fail when the socket

is closed from under it.
Enhancement: BOB can now clear a destination in under 1 second with the above fix.
	BOB also will do a thread dump when something really aweful happens,
	so that developers/users can help in debugging.
This commit is contained in:
sponge
2008-12-05 09:51:48 +00:00
parent c524231c6d
commit 701904d119
12 changed files with 114 additions and 45 deletions

View File

@@ -1,3 +1,4 @@
compile.on.save=false
do.depend=false
do.jar=true
javac.debug=true

View File

@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
<file>file:/root/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/MUXlisten.java</file>
</open-files>
</project-private>

View File

@@ -30,13 +30,31 @@ file.reference.mstreaming.jar-1=../ministreaming/java/build/mstreaming.jar
file.reference.NetBeansProjects-i2p.i2p=../i2p.i2p/
file.reference.streaming.jar=../../bob/i2p/i2p.i2p/build/streaming.jar
file.reference.streaming.jar-1=../streaming/java/build/streaming.jar
file.reference.wrapper-freebsd=../../installer/lib/wrapper/freebsd/
file.reference.wrapper-linux=../../installer/lib/wrapper/linux/
file.reference.wrapper-linux64=../../installer/lib/wrapper/linux64/
file.reference.wrapper-macosx=../../installer/lib/wrapper/macosx/
file.reference.wrapper-solaris=../../installer/lib/wrapper/solaris/
file.reference.wrapper-win32=../../installer/lib/wrapper/win32/
file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
file.reference.wrapper.jar-1=../../installer/lib/wrapper/freebsd/wrapper.jar
file.reference.wrapper.jar-2=../../installer/lib/wrapper/linux64/wrapper.jar
file.reference.wrapper.jar-3=../../installer/lib/wrapper/macosx/wrapper.jar
file.reference.wrapper.jar-4=../../installer/lib/wrapper/solaris/wrapper.jar
file.reference.wrapper.jar-5=../../installer/lib/wrapper/win32/wrapper.jar
includes=**
jar.compress=false
javac.classpath=\
${file.reference.i2p.jar-1}:\
${file.reference.i2ptunnel.jar}:\
${file.reference.mstreaming.jar-1}:\
${file.reference.streaming.jar-1}
${file.reference.streaming.jar-1}:\
${file.reference.wrapper.jar-1}:\
${file.reference.wrapper.jar}:\
${file.reference.wrapper.jar-2}:\
${file.reference.wrapper.jar-3}:\
${file.reference.wrapper.jar-4}:\
${file.reference.wrapper.jar-5}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false

View File

@@ -46,7 +46,7 @@ public class DoCMDS implements Runnable {
// FIX ME
// I need a better way to do versioning, but this will do for now.
public static final String BMAJ = "00", BMIN = "00", BREV = "01", BEXT = "-D";
public static final String BMAJ = "00", BMIN = "00", BREV = "01", BEXT = "-E";
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
private Socket server;
private Properties props;

View File

@@ -70,7 +70,7 @@ public class I2Plistener implements Runnable {
boolean g = false;
I2PSocket sessSocket = null;
serverSocket.setSoTimeout(1000);
serverSocket.setSoTimeout(100);
database.getReadLock();
info.getReadLock();
if(info.exists("INPORT")) {
@@ -107,32 +107,31 @@ public class I2Plistener implements Runnable {
// System.out.println("Exception " + e);
}
}
// System.out.println("I2Plistener: Close");
try {
serverSocket.close();
} catch(I2PException e) {
// nop
}
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
// System.out.println("STOP Thread count " + Thread.activeCount());
try {
Thread.sleep(1000); //sleep for 1000 ms (One second)
} catch(Exception e) {
// nop
}
}
// System.out.println("STOP Thread count " + Thread.activeCount());
// need to kill off the socket manager too.
I2PSession session = socketManager.getSession();
if(session != null) {
// System.out.println("I2Plistener: destroySession");
try {
session.destroySession();
} catch(I2PSessionException ex) {
// nop
}
// System.out.println("destroySession Thread count " + Thread.activeCount());
}
// System.out.println("I2Plistener: Waiting for children");
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(Exception e) {
// nop
}
}
// System.out.println("I2Plistener: Done.");
}
}

View File

@@ -119,20 +119,27 @@ die: {
// nop
}
}
System.out.println("I2PtoTCP: Going away...");
} catch(Exception e) {
System.out.println("I2PtoTCP: Owch! damn!");
break die;
}
} // die
try {
//System.out.println("I2PtoTCP: Close I2P");
I2P.close();
} catch(Exception e) {
tell = false;
}
//System.out.println("I2PtoTCP: Closed I2P");
try {
//System.out.println("I2PtoTCP: Close sock");
sock.close();
} catch(Exception e) {
tell = false;
}
//System.out.println("I2PtoTCP: Closed sock");
System.out.println("I2PtoTCP: Done");
}
}

View File

@@ -32,6 +32,7 @@ import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.util.Log;
import org.tanukisoftware.wrapper.WrapperManager;
/**
*
@@ -64,6 +65,7 @@ public class MUXlisten implements Runnable {
MUXlisten(NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
int port = 0;
InetAddress host = null;
this.tg = null;
this.database = database;
this.info = info;
this._log = _log;
@@ -207,23 +209,39 @@ die: {
break die;
}
} // die
// wait for child threads and thread groups to die
// System.out.println("MUXlisten: waiting for children");
while(tg.activeCount() + tg.activeGroupCount() != 0) {
tg.interrupt(); // unwedge any blocking threads.
try {
Thread.sleep(1000); //sleep for 1000 ms (One second)
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(InterruptedException ex) {
// nop
}
}
}
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
} catch(Exception e) {
// System.out.println("MUXlisten: Caught an exception" + e);
break quit;
}
} // quit
socketManager.destroySocketManager();
// zero out everything, just incase.
// This is here to catch when something fucks up REALLY bad.
if(tg != null) {
System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
System.out.println("BOB: MUXlisten: Please email the following dump to sponge@mail.i2p");
WrapperManager.requestThreadDump();
System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
System.out.println("BOB: MUXlisten: Please email the avove dump to sponge@mail.i2p");
}
// zero out everything, just incase.
try {
socketManager.destroySocketManager();
} catch(Exception e) {
// nop
}
try {
wlock();
try {
@@ -236,7 +254,20 @@ die: {
}
wunlock();
} catch(Exception e) {
return;
}
// This is here to catch when something fucks up REALLY bad.
if(tg != null) {
while(tg.activeCount() + tg.activeGroupCount() != 0) {
tg.interrupt(); // unwedge any blocking threads.
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(InterruptedException ex) {
// nop
}
}
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
}
}
}

View File

@@ -23,7 +23,6 @@
*/
package net.i2p.BOB;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -91,12 +90,16 @@ public class TCPio implements Runnable {
* the stream has been reached.
*
*/
// System.out.println("TCPio: End Of Stream");
return;
}
}
// System.out.println("TCPio: RUNNING = false");
} catch(Exception e) {
// Eject!!! Eject!!!
// System.out.println("TCPio: Caught an exception " + e);
return;
}
// System.out.println("TCPio: Leaving.");
}
}

View File

@@ -76,7 +76,6 @@ public class TCPlistener implements Runnable {
tgwatch = 2;
}
try {
// System.out.println("Starting thread count " + Thread.activeCount());
Socket server = new Socket();
listener.setSoTimeout(1000);
info.releaseReadLock();
@@ -87,7 +86,6 @@ public class TCPlistener implements Runnable {
spin = info.get("RUNNING").equals(Boolean.TRUE);
info.releaseReadLock();
database.releaseReadLock();
// System.out.println("Thread count " + Thread.activeCount());
try {
server = listener.accept();
g = true;
@@ -102,8 +100,13 @@ public class TCPlistener implements Runnable {
g = false;
}
}
//System.out.println("TCPlistener: destroySession");
listener.close();
} catch(IOException ioe) {
try {
listener.close();
} catch(IOException e) {
}
// Fatal failure, cause a stop event
database.getReadLock();
info.getReadLock();
@@ -120,17 +123,6 @@ public class TCPlistener implements Runnable {
}
}
//System.out.println("STOP!");
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
// System.out.println("STOP Thread count " + Thread.activeCount());
try {
Thread.sleep(1000); //sleep for 1000 ms (One second)
} catch(Exception e) {
// nop
}
}
// System.out.println("STOP Thread count " + Thread.activeCount());
// need to kill off the socket manager too.
I2PSession session = socketManager.getSession();
if(session != null) {
@@ -139,8 +131,16 @@ public class TCPlistener implements Runnable {
} catch(I2PSessionException ex) {
// nop
}
// System.out.println("destroySession Thread count " + Thread.activeCount());
}
//System.out.println("TCPlistener: Waiting for children");
while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
try {
Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(Exception e) {
// nop
}
}
//System.out.println("TCPlistener: Done.");
}
}

View File

@@ -152,6 +152,7 @@ public class TCPtoI2P implements Runnable {
// nop
}
}
System.out.println("TCPtoI2P: Going away...");
} catch(I2PException e) {
Emsg("ERROR " + e.toString(), out);
@@ -169,14 +170,19 @@ public class TCPtoI2P implements Runnable {
} catch(IOException ioe) {
}
try {
System.out.println("TCPtoI2P: Close I2P");
I2P.close();
} catch(Exception e) {
}
//System.out.println("TCPtoI2P: Closed I2P");
try {
System.out.println("TCPtoI2P: Close sock");
sock.close();
} catch(Exception e) {
}
//System.out.println("TCPtoI2P: Closed sock");
System.out.println("TCPtoI2P: Done.");
}
}