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

Reply via email to