[snmp] deadlock when destroying a context

Josh Bers jbers at bbn.com
Fri Jan 26 09:08:14 GMT 2007


Hi Tim,

Here's some code snippets. Good luck reproducing it... It seems to occur
when one thread is sending trap PDU's while another tries to destroy the
context. I put a delay between my last trap send and the destroy and haven't
seen it again.. (see lines marked // **uncomment to fix deadlock).

Create a Timer and schedule a SendPDU timer task fairly frequently (> 1 per
second) wait a bit, then call SendPDU.cancel() before canceling the Timer.

Josh

    class SendPDU extends java.util.TimerTask {
        private int trapCode = SnmpConstants.SNMP_TRAP_LINKUP;

        volatile boolean isScheduled = false;

        private SnmpContext mContext;

        /**
         * 
         */
        public SendPDU() {
            super();
            try {
                String host = TEST_MGMT_AGENT;
                if (TEST_MS_DEBUG_MODE) {
                    host = "localhost";
                }
                mContext = new SnmpContext(host, TRAP_PORT_NUMBER,
"0.0.0.0", "Standard");
          	   isScheduled = true;
            } catch (java.io.IOException exc) {
                System.out.println("IOException " + exc.getMessage());
            }
        }

        public void run () {
            if (!isScheduled) {
                return;
            }
            testSendPdu(trapCode);
            if (trapCode == SnmpConstants.SNMP_TRAP_LINKUP) {
                trapCode = SnmpConstants.SNMP_TRAP_LINKDOWN;
            } else if (trapCode == SnmpConstants.SNMP_TRAP_LINKDOWN) {
                trapCode = SnmpConstants.SNMP_TRAP_COLDSTART;
            } else if (trapCode == SnmpConstants.SNMP_TRAP_COLDSTART) {
                trapCode = SnmpConstants.SNMP_TRAP_WARMSTART;
            } else if (trapCode == SnmpConstants.SNMP_TRAP_WARMSTART) {
                trapCode = SnmpConstants.SNMP_TRAP_AUTHFAIL;
            } else {
                // loop back to beginning.
                trapCode = SnmpConstants.SNMP_TRAP_LINKUP;
            }
        }

        private void testSendPdu (int trapCode) {
            if (trapCode == SnmpConstants.SNMP_TRAP_COLDSTART) {
                sendPdu(trapCode, coldStart, "coldStart");
            } else if (trapCode == SnmpConstants.SNMP_TRAP_WARMSTART) {
                sendPdu(trapCode, warmStart, "warmStart");
            } else if (trapCode == SnmpConstants.SNMP_TRAP_AUTHFAIL) {
                sendPdu(trapCode, authenticationFailure,
"authenticationFailure");
            } else if (trapCode == SnmpConstants.SNMP_TRAP_LINKDOWN) {
                sendPdu(trapCode, linkDown, "linkDown");
            } else if (trapCode == SnmpConstants.SNMP_TRAP_LINKUP) {
                sendPdu(trapCode, linkUp, "linkUp");
            }
        }

        private void sendPdu (int genericTrap, String trapType, String
trapVal) {
            byte[] address = { 1, 1, 1, 1 };
            try {
                synchronized (mContext) {
                    TrapPduv1 pdu = new TrapPduv1(mContext);
                    pdu.setIpAddress(address);
                    pdu.setEnterprise("1.1");
                    pdu.setGenericTrap(genericTrap);
                    pdu.setSpecificTrap(1);
                    pdu.setTimeTicks(1000);

                    System.out.println(pdu.toString());
                    System.out.println("Sending " + trapVal);

                    if (genericTrap == SnmpConstants.SNMP_TRAP_LINKDOWN) {
                        varbind downIf = new varbind(IF_INDEX_OID, new
AsnInteger(1));
                        pdu.addOid(downIf);
                    } else if (genericTrap ==
SnmpConstants.SNMP_TRAP_LINKUP) {
                        varbind upIf = new varbind(IF_INDEX_OID, new
AsnInteger(1));
                        pdu.addOid(upIf);
                    }
                    pdu.send();
                }
            } catch (uk.co.westhawk.snmp.stack.PduException e) {
                System.out.println("PduException " + e);
            } catch (java.io.IOException exc) {
                System.out.println("IOException " + exc.getMessage());
            }
        }

        /*
         * (non-Javadoc)
         * 
         * @see java.util.TimerTask#cancel()
         */
        public boolean cancel () {
           // **uncomment to fix deadlock 
		// isScheduled = false;
            // workaround for deadlock in trap sending context 
        // **uncomment to fix deadlock
	//    synchronized (mContext) {
        //        try {
        //            mContext.wait(1000);
        //        } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
         //           e.printStackTrace();
           //     }
                mContext.destroy();
                mContext = null;
          //  }
            return super.cancel();
        }

        /*
         * (non-Javadoc)
         * 
         * @see java.lang.Object#finalize()
         */
        protected void finalize () throws Throwable {
            if (mContext != null) {
                mContext.destroy();
                mContext = null;
            }
            super.finalize();
        }

    }

> -----Original Message-----
> From: snmp-bounces at snmp.westhawk.co.uk 
> [mailto:snmp-bounces at snmp.westhawk.co.uk] On Behalf Of Tim Panton
> Sent: Friday, January 26, 2007 6:28 AM
> To: List for discussion of the Westhawk SNMP stack
> Subject: Re: [snmp] deadlock when destroying a context
> 
> 
> 
> On 23 Jan 2007, at 18:48, Josh Bers wrote:
> 
> > When using a context to send a trap pdu my code runs into a thread
> > deadlock
> > in the stack. One thread is destroying the context while 
> the other is
> > transmitting.  The stack should protect against this kind 
> of deadlock
> 
> Ugh, thanks for spotting this!
> 
> Do you have a small bit of test code that reproduces it ?
> (and any environment factors - dual core? etc)
> 
> I'll take a look next week and see if we can come up with a patch...
> 
> Tim.
> 
> 
> 
> 
> _______________________________________________
> snmp mailing list
> snmp at snmp.westhawk.co.uk 
> http://snmp.westhawk.co.uk/mailman/listinfo/snmp
> 





More information about the snmp mailing list