[snmp] Fix memory leak in SNMP (#8672)
* Fix memory leak in SNMP. When receiving an async request it is placed in a pending request queue. Not canceling it leads to infinty life cycle for those requests, filling up memory. * Test the canceling of the snmp aync request by its handler. Signed-off-by: Falk Bauer <falk.bauer@k-is.com>
This commit is contained in:
parent
6243ccb026
commit
54791d97d0
|
@ -52,6 +52,7 @@ import org.snmp4j.CommandResponderEvent;
|
||||||
import org.snmp4j.CommunityTarget;
|
import org.snmp4j.CommunityTarget;
|
||||||
import org.snmp4j.PDU;
|
import org.snmp4j.PDU;
|
||||||
import org.snmp4j.PDUv1;
|
import org.snmp4j.PDUv1;
|
||||||
|
import org.snmp4j.Snmp;
|
||||||
import org.snmp4j.event.ResponseEvent;
|
import org.snmp4j.event.ResponseEvent;
|
||||||
import org.snmp4j.event.ResponseListener;
|
import org.snmp4j.event.ResponseListener;
|
||||||
import org.snmp4j.mp.SnmpConstants;
|
import org.snmp4j.mp.SnmpConstants;
|
||||||
|
@ -175,6 +176,15 @@ public class SnmpTargetHandler extends BaseThingHandler implements ResponseListe
|
||||||
if (event == null) {
|
if (event == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.getSource() instanceof Snmp) {
|
||||||
|
// Always cancel async request when response has been received
|
||||||
|
// otherwise a memory leak is created! Not canceling a request
|
||||||
|
// immediately can be useful when sending a request to a broadcast
|
||||||
|
// address (Comment is taken from the snmp4j API doc).
|
||||||
|
((Snmp) event.getSource()).cancel(event.getRequest(), this);
|
||||||
|
}
|
||||||
|
|
||||||
PDU response = event.getResponse();
|
PDU response = event.getResponse();
|
||||||
if (response == null) {
|
if (response == null) {
|
||||||
Exception e = event.getError();
|
Exception e = event.getError();
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.openhab.core.library.types.DecimalType;
|
||||||
import org.openhab.core.library.types.OnOffType;
|
import org.openhab.core.library.types.OnOffType;
|
||||||
import org.openhab.core.library.types.StringType;
|
import org.openhab.core.library.types.StringType;
|
||||||
import org.snmp4j.PDU;
|
import org.snmp4j.PDU;
|
||||||
|
import org.snmp4j.Snmp;
|
||||||
import org.snmp4j.event.ResponseEvent;
|
import org.snmp4j.event.ResponseEvent;
|
||||||
import org.snmp4j.smi.Counter64;
|
import org.snmp4j.smi.Counter64;
|
||||||
import org.snmp4j.smi.Integer32;
|
import org.snmp4j.smi.Integer32;
|
||||||
|
@ -104,4 +105,27 @@ public class SnmpTargetHandlerTest extends AbstractSnmpTargetHandlerTest {
|
||||||
thingHandler.onResponse(event);
|
thingHandler.onResponse(event);
|
||||||
verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), eq(new DecimalType("12.4")));
|
verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), eq(new DecimalType("12.4")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCancelingAsyncRequest() {
|
||||||
|
setup(SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER, SnmpChannelMode.READ, SnmpDatatype.FLOAT);
|
||||||
|
PDU responsePDU = new PDU(PDU.RESPONSE,
|
||||||
|
Collections.singletonList(new VariableBinding(new OID(TEST_OID), new OctetString("12.4"))));
|
||||||
|
|
||||||
|
SnmpMock source = new SnmpMock();
|
||||||
|
|
||||||
|
ResponseEvent event = new ResponseEvent(source, null, null, responsePDU, null);
|
||||||
|
|
||||||
|
thingHandler.onResponse(event);
|
||||||
|
assertEquals(1, source.cancelCallCounter);
|
||||||
|
}
|
||||||
|
|
||||||
|
class SnmpMock extends Snmp {
|
||||||
|
public int cancelCallCounter = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cancel(PDU request, org.snmp4j.event.ResponseListener listener) {
|
||||||
|
++cancelCallCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue