Ruby Installer for Windows: use of Win32OLE bug causes crash

This is with the latest Ruby Installer for Windows, 181-13-rc2.

When I run the script below I see:

C:\localbin>diskspace.rb
(offline mode: enter name=value pairs on standard input)
^Z
(eval):1214: [BUG] Segmentation fault
ruby 1.8.1 (2003-12-25) [i386-mswin32]

This application has requested the Runtime to terminate it in an unusual
way.
Please contact the application’s support team for more information.

C:\localbin>

When I replace the get_diskinfo call with a call to fake_get_diskinfo,
skipping the Win32OLE calls, the program works fine (but is useless, of
course). I have added a comment to (closed) bug 522 on RubyForge.

Any help is appreciated.

#!ruby

require 'win32ole’
require 'cgi’
require ‘stringio’

outputfilename = “diskspace.htm”

hosts = []
File.open(“diskspace_hosts.txt”).each_line do |line|
next if line =~ /^\s*(#|$)/
hosts << line.chomp
end

hosts =%w(localhost localhost localhost somehost)

class DiskInfo
attr_reader :deviceid, :size, :freespace
def initialize(deviceid, size, freespace)
@deviceid, @size, @freespace = deviceid, size.to_i, freespace.to_i
end
def pct_free
freespace.to_f / size * 100
end
end

def fake_get_diskinfo(host)
result = []
result << DiskInfo.new(‘C:’, 10000000000, 5000000000)
result << DiskInfo.new(‘D:’, 20000000000, 8000000000)
end

Returns a list of DiskInfo objects for host, or nil

def get_diskinfo(host)
result = []
begin
wmi = WIN32OLE.connect(“winmgmts://#{host}/root/cimv2”)
rescue
return nil
end
disks = wmi.ExecQuery(“Select * from Win32_LogicalDisk”)
disks.each do |disk|
next if disk.Size.nil?
result << DiskInfo.new(disk.DeviceID, disk.Size, disk.FreeSpace)
end
result
end

Map freespace percentage to color codes

def alert_color(value)
case value
when 20…100; "lightgreen"
when 10…20; "yellow"
when 5…10; "orange"
when 0…5; "red"
else raise # Shouldn’t happen
end
end

diskdata = hosts.collect do |host|
[ host, get_diskinfo(host) ]
end

File.open(outputfilename, “w”) do |file|

Hack alert:

Since cgi.out writes to $DEFAULT_OUTPUT we capture the output in outstring by directing $DEFAULT_OUTPUT to it.

We need to do this because we want to strip the first 3 lines from the output (the HTTP header).

outstring = StringIO.new
$DEFAULT_OUTPUT = outstring

cgi = CGI.new(“html4”) # add HTML generation methods
cgi.out {
cgi.html {
cgi.head { “\n” + cgi.title{“Disk Space Overview”} } +
cgi.body { “\n” +
cgi.h2 { “Disk space by host by drive” } +
cgi.p { “Last updated: " + Time.now.to_s } +
cgi.table {
cgi.tr { cgi.th({“width” => “120%”, “align” => “left”}) { “Host” } + cgi.th { “Disk” } + cgi.th { “Total” } + cgi.th { “Free” } + cgi.th { “%” } } +
diskdata.collect do |host, di|
unless di
cgi.tr { cgi.td(“bgcolor” => “red”) { host } }
else
di.collect { |disk|
cgi.tr {
cgi.td { host } +
cgi.td { disk.deviceid } +
cgi.td { disk.size / 1024 ** 3 } +
cgi.td { disk.freespace / 1024 ** 3 } +
cgi.td(“bgcolor” => alert_color(disk.pct_free)) { “%3.2d” % disk.pct_free }
}
}
end
end.join(”\n")
}
}
}
}

outstring.rewind
file.puts outstring.readlines[3…-1] # Drop HTTP header
outstring.close
end

exit

···


Jos Backus / /// Sunnyvale, CA
_/ _/ _/
/ ///
_/ _/ _/ /
jos at catnook.com // //
/ require ‘std/disclaimer’

“Jos Backus” jos@catnook.com wrote in message

This is with the latest Ruby Installer for Windows, 181-13-rc2.

When I run the script below I see:

C:\localbin>diskspace.rb
(offline mode: enter name=value pairs on standard input)
^Z
(eval):1214: [BUG] Segmentation fault
ruby 1.8.1 (2003-12-25) [i386-mswin32]

Thanks for reporting this with an example … we (the Ruby-Installer team)
were
unable to test this before putting out the rc2 for want of such an example.

I do not know if we will able to fix it, but at least we will be able to
test it better.

– shanko

Thanks for reporting this with an example … we (the Ruby-Installer team)
were
unable to test this before putting out the rc2 for want of such an example.

I have been drilling down into this problem most of the afternoon, and I have
been stripping diskspace.rb to where a source change of removing a specific
line causes an error. So it looks like some kind of memory corruption problem
during the lexing/parsing phase? I’ll dig further.

I do not know if we will able to fix it, but at least we will be able to
test it better.

Thanks. Please let me know if you can repro this problem. I am on Win2K3
Server.

Cheers,

···

On Sat, May 08, 2004 at 06:53:54AM +0900, Shashank Date wrote:

Jos Backus / /// Sunnyvale, CA
_/ _/ _/
/ ///
_/ _/ _/ /
jos at catnook.com // //
/ require ‘std/disclaimer’

Oops, I forgot to mention that the specific line I’m removing is EMPTY. And I
can reproduce this in different parts of the source file. It’s definitely
vertical whitespace-related. Oddest bug I’ve seen in a while.

···

On Sat, May 08, 2004 at 08:06:58AM +0900, Jos Backus wrote:

I have been drilling down into this problem most of the afternoon, and I have
been stripping diskspace.rb to where a source change of removing a specific
line causes an error. So it looks like some kind of memory corruption problem
during the lexing/parsing phase? I’ll dig further.


Jos Backus / /// Sunnyvale, CA
_/ _/ _/
/ ///
_/ _/ _/ /
jos at catnook.com // //
/ require ‘std/disclaimer’

“Jos Backus” jos@catnook.com wrote in message

Please let me know if you can repro this problem. I am on Win2K3
Server.

Yes, I was able to reproduce this also on Win XP (Home).
– shanko

“Jos Backus” jos@catnook.com wrote in message

Oops, I forgot to mention that the specific line I’m removing is EMPTY.
And I
can reproduce this in different parts of the source file. It’s definitely
vertical whitespace-related. Oddest bug I’ve seen in a while.

Strange ! Which line is that ?
– shanko

Good news: I can no longer reproduce this using yesterday’s CVS -HEAD. The
problem also seems to have disappeared when using this snapshot (in case you
can’t easily build from source).

ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.9.0-20040402-i386-mswin32.zip

Perhaps you can verify this result, that would be helpful. This would mean
that it’s not a win32ole issue but a Ruby problem that has recently been
fixed. Hopefully whatever the fix is makes it into 1.8.2.

···

On Sat, May 08, 2004 at 06:48:54PM +0900, Shashank Date wrote:

Yes, I was able to reproduce this also on Win XP (Home).


Jos Backus / /// Sunnyvale, CA
_/ _/ _/
/ ///
_/ _/ _/ /
jos at catnook.com // //
/ require ‘std/disclaimer’

“Jos Backus” jos@catnook.com wrote in message

Oops, I forgot to mention that the specific line I’m removing is EMPTY.
And I
can reproduce this in different parts of the source file. It’s definitely
vertical whitespace-related. Oddest bug I’ve seen in a while.

Strange ! Which line is that ?

There are a few positions in the file where this happens. Starting from the
bottom I can “move” the empty line I’m deleting up and get the same error, but
it doesn’t work near the top of the file. I’m assuming the bug is such that
Ruby needs to have seen a declaration of a particular kind before the problem
manifests itself. In the attached file, which works in its current form on 2K3
I was able to trigger the problem arbitrarily by extending some of the string
constants beyond a certain length or removing expression terms (e.g. 1 * 1 →

  1. in addition to changing the vertical whitespace (horizontal whitespace
    seemed to have no influence). I saw the line issue at line 74 in the attached
    file, and the first problem occurred when I tried adding an “align” => “right”
    argument to a cgi.td call. But I’d be surprised if you could duplicate the
    subtle failures 2K3 showed on XP, as I wasn’t able to.

It sure would be nice to hear the win32ole author pipe up.

diskspace_noerror.rb (2.4 KB)

···

On Sat, May 08, 2004 at 06:48:54PM +0900, Shashank Date wrote:

– shanko


Jos Backus / /// Sunnyvale, CA
_/ _/ _/
/ ///
_/ _/ _/ /
jos at catnook.com // //
/ require ‘std/disclaimer’

“Jos Backus” jos@catnook.com wrote in message
news:20040513070756.GA72004@lizzy.catnook.com

Yes, I was able to reproduce this also on Win XP (Home).

Good news: I can no longer reproduce this using yesterday’s CVS -HEAD. The
problem also seems to have disappeared when using this snapshot (in case
you
can’t easily build from source).

ftp://ftp.ruby-lang.org/pub/ruby/binaries/mswin32/ruby-1.9.0-20040402-i386-mswin32.zip

Perhaps you can verify this result, that would be helpful. This would mean
that it’s not a win32ole issue but a Ruby problem that has recently been
fixed. Hopefully whatever the fix is makes it into 1.8.2.

Good news indeed ! I will give that a try over the week-end.

I will request you to consider joining the Ruby Installer team. Your
experience in
trying to track down bugs and fix them on the Win32 platform is very
valuable and we
all will greatly benefit from it.
http://rubyforge.org/projects/rubyinstaller/

– shanko

···

On Sat, May 08, 2004 at 06:48:54PM +0900, Shashank Date wrote:

“Jos Backus” jos@catnook.com wrote in message

In the attached file, which works in its current form on 2K3

I was able to run it on Win XP without a problem. Incidently I was also able
to run your original program with minor modifications (see line 13 and
94 thru 97 of the attached …).

But it failed when I uncommented lines 94 and 97 ** AND ** installed
the flash disk so that there were two logical drives.

I was able to trigger the problem arbitrarily by extending some of the
string
constants beyond a certain length or removing expression terms (e.g. 1 *
1 →

  1. in addition to changing the vertical whitespace (horizontal whitespace
    seemed to have no influence). I saw the line issue at line 74 in the
    attached
    file, and the first problem occurred when I tried adding an “align” =>
    “right”
    argument to a cgi.td call.

I will give that a try …

It sure would be nice to hear the win32ole author pipe up.

At this point it does not seem like a win32ole issue since the following
snippet
works (at least on Win XP and ruby-1.8.1-rc13):

···

#---------------------------------------------
require ‘win32ole’

host = “localhost”
wmi = WIN32OLE.connect(“winmgmts://#{host}/root/cimv2”)
disks = wmi.ExecQuery(“Select * from Win32_LogicalDisk”)
p disks

disks.each do |disk|
next if disk.Size.nil?
p disk.DeviceID, disk.Size, disk.FreeSpace
end
#---------------------------------------------

But it breaks the moment you add any CGI call. Now what is more likely to be
the culprit, cgi.rb et al. (all written in Ruby afaIk) or win32ole.so? My
money’s on a module that interacts heavily with COM/OLE/the Win32 API, not the
interpreter. Adding cgi.rb to the program does trigger the problem but I’m
confident that the real problem is inside win32ole. Note also that in the most
stripped example, among others, removing the require ‘fileutils’ makes the
error go away. That to me smells like a file descriptor/memory issue of some
sort.

Of course I could be all wrong :slight_smile: Methinks the win32ole author should be able
to track this one down using the failing examples given. That sure would be
nice, as the win32ole stuff is incredibly powerful.

···

On Mon, May 10, 2004 at 12:43:53PM +0900, Shashank Date wrote:

It sure would be nice to hear the win32ole author pipe up.

At this point it does not seem like a win32ole issue since the following
snippet
works (at least on Win XP and ruby-1.8.1-rc13):
#---------------------------------------------
require ‘win32ole’

host = “localhost”
wmi = WIN32OLE.connect(“winmgmts://#{host}/root/cimv2”)
disks = wmi.ExecQuery(“Select * from Win32_LogicalDisk”)
p disks

disks.each do |disk|
next if disk.Size.nil?
p disk.DeviceID, disk.Size, disk.FreeSpace
end
#---------------------------------------------


Jos Backus / /// Sunnyvale, CA
_/ _/ _/
/ ///
_/ _/ _/ /
jos at catnook.com // //
/ require ‘std/disclaimer’