UPnP Running out of resources

Oct 23, 2012 at 1:28 PM

Hi,

Have you ever seen this error:

WARNING> 2012-10-21T20:08:23 UPnP --> Error trying to enable UPnP -> System.Runtime.InteropServices.COMException (0x80070008): Not enough storage is available to process this command. (Exception from HRESULT: 0x80070008)
   at UPNPLib.IUPnPDeviceFinder.StartAsyncFind(Int32 lFindData)
   at ManagedUPnP.Discovery.Start()
   at ManagedUPnP.Discovery.FindDevices(String uriString, Int32 timeoutMS, Int32 maxDevices, Boolean& searchCompleted, AddressFamilyFlags addressFamily, Boolean resolveNetworkInterfaces)
   at MCEBuddy.Engine.UPnP.EnableUPnP(Int32 onPort, Boolean verbose)
WARNING> 2012-10-21T20:18:23 UPnP --> Error trying to enable UPnP -> System.Runtime.InteropServices.COMException (0x80070008): Not enough storage is available to process this command. (Exception from HRESULT: 0x80070008)
   at UPNPLib.IUPnPDeviceFinder.StartAsyncFind(Int32 lFindData)
   at ManagedUPnP.Discovery.Start()
   at ManagedUPnP.Discovery.FindDevices(String uriString, Int32 timeoutMS, Int32 maxDevices, Boolean& searchCompleted, AddressFamilyFlags addressFamily, Boolean resolveNetworkInterfaces)
   at MCEBuddy.Engine.UPnP.EnableUPnP(Int32 onPort, Boolean verbose)

 

Apparently after running hte Discovery code in a loop every 10 minutes for about 15 days the systems bugs out with this error. Hard disk space is not an issue, don't know what it's referring to - memory?

 

One of the users reported this issue.

Oct 23, 2012 at 1:38 PM

I understand you're ucing COM API's to communication - I suspect it would be a memory leak somewhere.

Oct 24, 2012 at 2:40 AM

I noticed you've implemented Dispose methods for each class but no one is calling the Dispose methods. could that be leading to the issue?

Coordinator
Oct 24, 2012 at 11:39 AM
Edited Oct 24, 2012 at 11:42 AM

First of all, you should never need to continually call the discovery method, simply setup an async discovery, start it discovering and leave it running, it is designed to automatically raise events as new devices are detected. See the AutoEventedDiscoveryServices<(Of <(<'T>)>)> class, for an example you can look at the ManagedUPnPTest application which is supplied with the framework.

Basically you create your instance of AutoEventedDiscoveryServices<T> where T is of IAutoDiscoveryService which simply raises events, the CanCreateServiceFor and CreateServiceFor events allow you to create an object which implements the IAutoDiscoveryService for an actual UPnP service which is discovered. This is how you should be doing it for constant monitoring of devices.

However, if you must constantly create new discovery objects then yes you should be disposing them, during the normal use of the framework this would not be required as they would simply be disposed by the GC when they go out of scope, you will need to dispose them if you are constantly scanning due to the Multi Threaded Apartment COM object creation, so you can choose to either create a new service directly from each service using its UUID and then disposing the multi threaded one, or use the proper monitoring method as explained above.

So it is not a memory leak per-se, the objects are still referenced by the COM object model which is why they are not disposed automatically until the program ends, so you must either dispose them yourself or set-up an async discover service. I did not realise you were using the framework in this manner.

See the doco on the AutoEventedDiscoveryServices class for more information.

I hope this helps.

Oct 24, 2012 at 1:34 PM

Yes thanks that is helpful. The reason i'm using a new scan every 10 minutes ie beause I've come across many "problematic" UPnP routers (I own one also) which tend to "lose" the mapping after a few hours. hence I thought the best way to do it is the just scan for devices and "reinitialize" them (it's just a mapping).

But I see what's happening above. I have a question, since the Discovery class is a static class - how do I dispose off the Discovey object?

Coordinator
Oct 24, 2012 at 9:02 PM
Edited Oct 24, 2012 at 9:17 PM

It's not the discovery class itself that Is causing the memory to not be freed until the program closes, its the services which have been created as a result of the discovery, so you need to dispose them.

When I have some more time I will look into it in more detail, however, in the meantime you are free to debug the framework yourself, the first thing I would check is to make sure the Service classes are being disposed by the GC.

However as I stated above, I think you will find it is a problem with the Multi Threaded Apartment environment and the COM objects themselves not being released because of the MTA. This means whenever you use a service created in a separate thread, you will need to create the service again in the main application thread using the device UID.

Oct 25, 2012 at 12:50 AM

Okay so I'm disposing the services now after each discovery. Maybe it'll be a good idea not to make Discovery class static so that when the class it Disposed in the destructor you can dispose off the services automatically.

Coordinator
Oct 25, 2012 at 2:53 AM

Yes that is correct, however, it is not possible to get the discovery class to dispose automatically because it no idea which services you have used and which ones you havnt, the framework wasnt really designed to be used in the manner you are using it, but it will be possible if you dispose the services.

Oct 25, 2012 at 4:49 AM

With the way it's currently setup, I can't instantiate a class and use the FindServices method, just a FYI so I need to use the static version of it. Maybe that flexibility will allow me to create a Discovery object, use the class and then dispose off the discovery object which should dispose off any services / objects created by it.