On Jan 12, 2010, at 4:10 PM, Luis Lavena wrote:

> On Jan 12, 6:19 pm, Chuck Remes <cremes.devl... / mac.com> wrote:
>> In my ruby code I am making a call out to a COM object that is
>> returning an array of objects. I extract some information from these
>> objects and then request a new batch to do the same work all over  
>> again.
>>
>> Even though I am clearing the received array out, my program slowly
>> leaks memory until it hits its limit (around 1.4 GB on Windows) and
>> dies.
>>
>> I have tried adding my_object.ole_free calls everywhere, but that has
>> not helped at all. I've looked through the archives (back to 2004)  
>> and
>> saw that this was a common issue years ago. I had hoped it would be
>> fixed by now.
>>
>> Does anyone have any suggestions on how to force these unused objects
>> to get GC'ed? This program needs to run a long time so a memory leak
>> is absolutely fatal.
>
> Please include exact and complete version of Ruby you're using (ruby -
> v) and under which Windows flavor.
>
> Also, if this can be reproducible with any COM object, include a
> sample script for us to reproduce in other Windows version and Ruby
> version combinations.

Sorry for not providing more details. I actually thought this might be  
a "known" issue.

Here's some code. This is running against 1.8.6-p383 (from  
rubyinstaller.org) on Windows XP SP3 plus all the latest patches  
(Windows Update runs weekly).

def register_callbacks
   event.on_event('DataResolved') do |collection, error|
     save collection unless error
     @flag1 = false
   end
end

def save collection
   collection.each do |data|
     doc = {
       'field1' => data.Property1.to_i,
       'field2' => data.Property2.to_f,
       'field3' => data.Property3
     }

     @mongo_collection.insert doc
     data.ole_free
   end
   collection.ole_free
end

def request_data start_date, end_date
   @start_date = start_date
   @end_date = end_date

   @flag1 = true

   request = @com.CreateDataRequest

   range_start_method = request.ole_method_help 'RangeStart'
   range_end_method = request.ole_method_help 'RangeEnd'

   request._setproperty range_start_method.dispid, [@start_date],  
[VT_DATE]
   request._setproperty range_end_method.dispid, [@end_date], [VT_DATE]

   @com.RequestData request
end

I have a method that makes a function call on the COM object  
(#request_data). When the function has data to return, it generates a  
"DataResolved" event which triggers my callback which was registered  
once at the beginning of execution. The callback calls #save and loops  
through the collection and pulls some properties into a hash which  
then gets inserted into mongodb. When the collection is exhausted, I  
go back to #request_data and make another call on the COM object to  
request the next batch.

The collection returned is usually around 30MB. I don't leak all 30MB  
each time through; it leaks a big percentage of it though (30 to 50%).

When Task Manager tells me the ruby.exe process is taking up around  
1.4GB, the process just exits.

Unfortunately this application is not available to the general public  
so I can't provide a script for someone to independently verify this. :(

cr