I'm trying my hand at debugging this....
It looks to me like the problem is that a ConnectionHandler
was removed from the OCM twice, and that LRUQueue.remove
should check the QItem pointer before calling list.remove().
But maybe a ConnectionHandler should never be removed twice.
*** src/freenet/support/LRUQueue.java 2003-09-21 16:05:15.000000000 -0400
--- src/freenet/support/LRUQueue.java.~1.4.~ 2003-09-15 22:05:02.000000000 -0400
***************
*** 47,56 ****
}
public final synchronized void remove(Object obj) {
! QItem i = (QItem)hash.remove(obj);
! if (i != null) { // may remove item not on LRUQueue.
! list.remove(i);
! }
}
public Enumeration elements() {
--- 47,53 ----
}
public final synchronized void remove(Object obj) {
! list.remove((QItem)hash.remove(obj));
}
public Enumeration elements() {
----- annotated traceback ------
java.lang.NullPointerException
at
freenet.support.DoublyLinkedListImpl.remove
(DoublyLinkedListImpl.java:195)
194 public DoublyLinkedList.Item remove(DoublyLinkedList.Item i) {
195 DoublyLinkedList.Item next = i.getNext(), prev = i.getPrev();
The null pointer must be i. getNext and getPrev do not dereference
any pointers.
at
freenet.support.LRUQueue.remove
(LRUQueue.java:50)
16 private final Hashtable hash = new Hashtable();
49 public final synchronized void remove(Object obj) {
50 list.remove((QItem)hash.remove(obj));
As it happens, hash.remove will return null if obj is
not in the hashtable.
------------
(java.util.Hashtable)
java.util
Interface Map
public Object remove(Object key)
Removes the mapping for this key from this map if present
(optional operation).
Parameters:
key - key whose mapping is to be removed from the map.
Returns:
previous value associated with specified key, or null if there
was no mapping for key. A null return can also indicate that
the map previously associated null with the specified key, if
the implementation supports null values.
Throws:
UnsupportedOperationException - if the remove method is not
supported by this map.
--------------
at
freenet.OpenConnectionManager.remove
(OpenConnectionManager.java:130)
56 private final LRUQueue lru = new LRUQueue();
110 ConnectionHandler remove(ConnectionHandler ch) {
130 lru.remove(ch); // is synchronized(lru)
at
freenet.ConnectionHandler.removeFromOCM
(ConnectionHandler.java:2723)
46 private final OpenConnectionManager ocm;
149 private Identity identity;
235 public ConnectionHandler(OpenConnectionManager ocm,
245 this.ocm = ocm;
253 this.identity = link.getPeerIdentity();
2721 private final void removeFromOCM() {
2722 if (identity != null)
2723 ocm.remove(this);
at
freenet.ConnectionHandler.terminate
(ConnectionHandler.java:2763)
public void terminate() {
// if(unregisteredFromOCM) decOpenButNotOnOCM();
logDEBUG = Core.logger.shouldLog(Logger.DEBUG,this);
if(logDEBUG) logDEBUG("Terminating", true);
// Unconditionally remove the connection handler
// from the OCM
// This should be the ONLY place we call it from
// To avoid leaking conns, we keep everything open in the OCM
removeFromOCM();
at
freenet.ConnectionHandler.queuedClose
(ConnectionHandler.java:1249)
(omitted debug stuff.)
public void queuedClose() {
terminate();
}
at
freenet.transport.AbstractSelectorLoop.queueClose
(AbstractSelectorLoop.java:680)
protected void queueClose(ClosePair chan) {
if(chan.attachment != null)
((NIOCallback)(chan.attachment)).queuedClose();
at
freenet.transport.AbstractSelectorLoop.queueClose
(AbstractSelectorLoop.java:728)
40 private static Hashtable closeUniqueness = null; //FIXME:hardcoded
119 if (closeUniqueness == null)
closeUniqueness = new Hashtable(512);
161 protected final class ClosePair {
public Connection conn;
public Object attachment;
public SocketChannel sc;
public long timeStamp; //debugging. Can be removed eventually
public ClosePair(Connection conn, Object attachment,
SocketChannel sc) {
this.conn = conn;
this.attachment = attachment;
this.sc = sc;
timeStamp = System.currentTimeMillis();
}
public String toString() {
return conn.toString()+":"+((attachment == null) ? "(null)" :
attachment.toString())+":"+sc;
}
}
716 public void queueClose(SocketChannel chan, NIOCallback nc) {
if(chan == null) return;
Socket sock = chan.socket();
if(sock == null) return;
Connection c = tcpConnection.getConnectionForSocket(sock);
if(c == null) {
if(chan.isConnected() && chan.isOpen())
throw new IllegalArgumentException("Fed socket not connected "+
"to a tcpConnection!: "+chan);
else return;
}
if (closeUniqueness.containsKey(c)) return;
728 queueClose(new ClosePair(c,nc,chan));
}
at
freenet.transport.ReadSelectorLoop.inspectChannels
(ReadSelectorLoop.java:307)
180 protected final boolean inspectChannels() {
193 while (i.hasNext()) {
SelectionKey current = (SelectionKey)i.next();
NIOReader nc = (NIOReader)current.attachment();
SocketChannel sc = (SocketChannel)current.channel();
int size=0;
try { ...
try { ...
} catch (IOException e) { ...
size = -1;
}
} catch (Throwable e) { ...
size = -1; // try unregistering it...
}
294 if (size == -1) {
//TODO: log that this channel got closed.
// and mark its Connection object as closed. (that'll be tricky)
if(logDebug)
Core.logger.log(this, "Closed (read -1): "+current,
Logger.DEBUG);
SelectionKey k = sc.keyFor(sel);
k.attach(null);
k.cancel();
// queueClose BEFORE notifying unregistration.
// So that if we wait on unregistration, and then check closure,
// we get the right sane answer.
307 queueClose((SocketChannel)sc, nc);
nc.unregistered();
noneWorking = false;
310 } else if ...
344 }
at
freenet.transport.AbstractSelectorLoop.loop
(AbstractSelectorLoop.java:625)
at
freenet.transport.ReadSelectorLoop.run
(ReadSelectorLoop.java:436)
public final void run() {
loop();
}
at
java.lang.Thread.run(Thread.java:536)
--
Edward J. Huff <[EMAIL PROTECTED]>
_______________________________________________
Devl mailing list
[EMAIL PROTECTED]
http://dodo.freenetproject.org/cgi-bin/mailman/listinfo/devl