Details

    • Type: Improvement Improvement
    • Status: Open Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: win32ole, Windows
    • Labels:
      None
    • Environment:
      jruby 1.6.5 (ruby-1.8.7-p330) (2011-10-25 9dcd388) (Java HotSpot(TM) Client VM 1.6.0_26) [Windows XP-x86-java]
    • Testcase included:
      yes
    • Number of attachments :
      0

      Description

      (ruby-wmi gem)

      loop {::WMI::Win32_Process.find(:all, :conditions =>

      {'Name' => 'bash.exe'}

      ); GC.start }

      This eventually fails with this backtrace in jruby, not MRI:

      Java::OrgRacobCom::ComFailException: Invoke of: ExecQuery
      Source: SWbemServicesEx
      Description: Server buffers are full and data cannot be accepted
      ...

      full trace:
      https://gist.github.com/1373677

      following jruby memory usage from jconsolet appears not to be leaking, and this even might be expected for all I know, but it is odd that MRI doesn't show it, so might be a bug somewhere.

      My hunch is that (elsewhere, same code base) using win32ole "in a loop" from one thread caused this when trying to create a new thread, later:

      Exception in thread "RubyThread-2: go.rb:1" java.lang.OutOfMemoryError: unable to create new native thread

      Thanks!
      roger

        Activity

        Hide
        Roger Pack added a comment -

        the "unable to create new native thread" may have been caused by a different issue (JRUBY-6248) I believe. Also it "might" be an XP+32bit only problem.

        Show
        Roger Pack added a comment - the "unable to create new native thread" may have been caused by a different issue ( JRUBY-6248 ) I believe. Also it "might" be an XP+32bit only problem.
        Hide
        Roger Pack added a comment -

        simpler example:

        {{{
        require 'win32ole'
        wmi = WIN32OLE.connect("winmgmts://")
        loop {
        processes = wmi.ExecQuery("select * from win32_process where ProcessId = #

        {Process.pid}

        ")
        }}}

        Show
        Roger Pack added a comment - simpler example: {{{ require 'win32ole' wmi = WIN32OLE.connect("winmgmts://") loop { processes = wmi.ExecQuery("select * from win32_process where ProcessId = # {Process.pid} ") }}}
        Hide
        Roger Pack added a comment -

        Just ran into this with jruby 1.6.5 (ruby-1.8.7-p330) (2011-10-25 9dcd388) (Java HotSpot(TM) Client VM 1.6.0_32) [Windows 7-x86-java]

        so it's not an "XP" thing.

        Show
        Roger Pack added a comment - Just ran into this with jruby 1.6.5 (ruby-1.8.7-p330) (2011-10-25 9dcd388) (Java HotSpot(TM) Client VM 1.6.0_32) [Windows 7-x86-java] so it's not an "XP" thing.
        Hide
        Roger Pack added a comment -

        Able to reproduce it with jruby 1.7.0.preview1 (ruby-1.9.3-p203) (2012-05-19 00c8c98) (Java HotSpot(TM) 64-Bit Server VM 1.7.0_04) [Windows 7-amd64-java] so it's not a 32-bit thing.

        Show
        Roger Pack added a comment - Able to reproduce it with jruby 1.7.0.preview1 (ruby-1.9.3-p203) (2012-05-19 00c8c98) (Java HotSpot(TM) 64-Bit Server VM 1.7.0_04) [Windows 7-amd64-java] so it's not a 32-bit thing.
        Hide
        Roger Pack added a comment -

        The monitor from visualvm shows memory usage "pegged" at 50MB while the windows' memory usage goes up and up, so I'm guessing it's not a java-style reference leak, but an internal one to the COM core somehow.

        Show
        Roger Pack added a comment - The monitor from visualvm shows memory usage "pegged" at 50MB while the windows' memory usage goes up and up, so I'm guessing it's not a java-style reference leak, but an internal one to the COM core somehow.
        Hide
        Roger Pack added a comment -

        Interestingly, if I run this code:

        {{{
        require 'win32ole'
        wmi = WIN32OLE.connect("winmgmts://")
        loop {
        processes = wmi.ExecQuery("select * from win32_process where ProcessId = #

        {Process.pid}

        ")
        for proc in processes
        proc.ole_free
        end

        processes.ole_free
        }

        wmi.ole_free
        }}}

        Then it appears to not leak (gets to around 100MB resident used, stays there). I don't quite understand this, it would seem to infer that the problem is "only" because java's GC can't "count" the bytes right, since they're in native code, and so doesn't see it as a high priority to collect them. But even doing a GC.start which cleans up all RubyWin32OLE.java objects, and adding an extra finalizer to them to call safeRelease on the internal object, or running it with -Djacob.auto_gc don't seem to fix it, so I'm not sure what exactly is going on here. But it seems to be an acceptable work around...

        Show
        Roger Pack added a comment - Interestingly, if I run this code: {{{ require 'win32ole' wmi = WIN32OLE.connect("winmgmts://") loop { processes = wmi.ExecQuery("select * from win32_process where ProcessId = # {Process.pid} ") for proc in processes proc.ole_free end processes.ole_free } wmi.ole_free }}} Then it appears to not leak (gets to around 100MB resident used, stays there). I don't quite understand this, it would seem to infer that the problem is "only" because java's GC can't "count" the bytes right, since they're in native code, and so doesn't see it as a high priority to collect them. But even doing a GC.start which cleans up all RubyWin32OLE.java objects, and adding an extra finalizer to them to call safeRelease on the internal object, or running it with -Djacob.auto_gc don't seem to fix it, so I'm not sure what exactly is going on here. But it seems to be an acceptable work around...

          People

          • Assignee:
            Thomas E Enebo
            Reporter:
            Roger Pack
          • Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: