From nobody at rubyforge.org Sun Jan 30 09:15:18 2011 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 30 Jan 2011 09:15:18 -0500 (EST) Subject: [ruby-oci8-commit] [421] trunk/ruby-oci8: * ext/oci8/oci8.c: fix SEGV which depends on GC order. Message-ID: <20110130141518.C569719782DB@rubyforge.org> Revision: 421 Author: kubo Date: 2011-01-30 09:15:18 -0500 (Sun, 30 Jan 2011) Log Message: ----------- * ext/oci8/oci8.c: fix SEGV which depends on GC order. * ext/oci8/oraconf.rb: check Oracle client's cpu type on Solaris as on Linux and Mac OS X. change error messages on Mac OS X to suggest to set RC_ARCHS=x86_64 when mkmf.log contains messages such as 'missing required architecture i386 in file.' Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/oci8.c trunk/ruby-oci8/ext/oci8/oraconf.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2010-12-26 11:18:22 UTC (rev 420) +++ trunk/ruby-oci8/ChangeLog 2011-01-30 14:15:18 UTC (rev 421) @@ -1,3 +1,10 @@ +2011-01-30 KUBO Takehiro + * ext/oci8/oci8.c: fix SEGV which depends on GC order. + * ext/oci8/oraconf.rb: check Oracle client's cpu type on Solaris as + on Linux and Mac OS X. change error messages on Mac OS X to suggest + to set RC_ARCHS=x86_64 when mkmf.log contains messages such as + 'missing required architecture i386 in file.' + 2010-12-26 KUBO Takehiro * ext/oci8/ocinumber.c, lib/oci8/bindtype.rb, test/test_oranumber.rb: add OraNumber#has_decimal_part? and OCI8::BindType::BasicNumberType. @@ -82,6 +89,7 @@ 2010-08-15 KUBO Takehiro * ext/oci8/lob.c, ext/oci8/object.c, ext/oci8/oci8.h, lib/oci8/object.rb: support LOB datatypes in Oracle objects. + (reported by Michael Sexton) * ext/oci8/ocihandle.c: fix SEGV in finalizer when temporary LOBs are used. This bug was introduced by the previous commit. Modified: trunk/ruby-oci8/ext/oci8/oci8.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.c 2010-12-26 11:18:22 UTC (rev 420) +++ trunk/ruby-oci8/ext/oci8/oci8.c 2011-01-30 14:15:18 UTC (rev 421) @@ -34,7 +34,35 @@ #define OCI8_STATE_SERVER_ATTACH_WAS_CALLED 0x02 static VALUE cOCI8; +static VALUE cSession; +static VALUE cServer; +typedef struct oci8_svcctx_associate { + oci8_base_t base; + oci8_svcctx_t *svcctx; +} oci8_svcctx_associate_t; + +static void oci8_svcctx_associate_free(oci8_base_t *base) +{ + oci8_svcctx_associate_t *assoc = (oci8_svcctx_associate_t *)base; + if (assoc->svcctx != NULL) { + switch (assoc->base.type) { + case OCI_HTYPE_SESSION: + assoc->svcctx->session = NULL; + break; + case OCI_HTYPE_SERVER: + assoc->svcctx->server = NULL; + break; + } + } +} + +static oci8_base_class_t oci8_svcctx_associate_class = { + NULL, + oci8_svcctx_associate_free, + sizeof(oci8_svcctx_associate_t), +}; + static void oci8_svcctx_mark(oci8_base_t *base) { oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base; @@ -66,8 +94,10 @@ oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base; svcctx->executing_thread = Qnil; - svcctx->session = DATA_PTR(rb_obj_alloc(oci8_cOCIHandle)); - svcctx->server = DATA_PTR(rb_obj_alloc(oci8_cOCIHandle)); + svcctx->session = DATA_PTR(rb_obj_alloc(cSession)); + svcctx->server = DATA_PTR(rb_obj_alloc(cServer)); + ((oci8_svcctx_associate_t *)svcctx->session)->svcctx = svcctx; + ((oci8_svcctx_associate_t *)svcctx->server)->svcctx = svcctx; svcctx->pid = getpid(); svcctx->is_autocommit = 0; #ifdef HAVE_TYPE_RB_BLOCKING_FUNCTION_T @@ -976,6 +1006,8 @@ cOCI8 = rb_define_class("OCI8", oci8_cOCIHandle); #endif cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_class); + cSession = oci8_define_class_under(cOCI8, "Session", &oci8_svcctx_associate_class); + cServer = oci8_define_class_under(cOCI8, "Server", &oci8_svcctx_associate_class); oracle_client_vernum = INT2FIX(oracle_client_version); if (have_OCIClientVersion) { Modified: trunk/ruby-oci8/ext/oci8/oraconf.rb =================================================================== --- trunk/ruby-oci8/ext/oci8/oraconf.rb 2010-12-26 11:18:22 UTC (rev 420) +++ trunk/ruby-oci8/ext/oci8/oraconf.rb 2011-01-30 14:15:18 UTC (rev 421) @@ -378,6 +378,18 @@ private + def self.make_proc_to_check_cpu(expect) + Proc.new do |file| + so = MiniSOReader.new(file) + if so.cpu == expect + true + else + puts " skip: #{file} is for #{so.cpu} cpu." + false + end + end + end + def self.check_ic_dir puts "checking for load library path... " STDOUT.flush @@ -390,6 +402,8 @@ so_ext = 'so' nls_data_ext = nil check_proc = nil + is_32bit = [nil].pack('p').size == 4 + is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102 case RUBY_PLATFORM when /mswin32|cygwin|mingw32|bccwin32/ oci_basename = 'oci' @@ -398,44 +412,29 @@ @@ld_envs = %w[PATH] so_ext = 'dll' when /i.86-linux/ - check_proc = Proc.new do |file| - so = MiniSOReader.new(file) - if so.cpu == :i386 - true - else - puts " skip: #{file} is for #{so.cpu} cpu." - false - end - end + check_proc = make_proc_to_check_cpu(:i386) when /ia64-linux/ - check_proc = Proc.new do |file| - so = MiniSOReader.new(file) - if so.cpu == :ia64 - true - else - puts " skip: #{file} is for #{so.cpu} cpu." - false - end - end + check_proc = make_proc_to_check_cpu(:ia64) when /x86_64-linux/ # RUBY_PLATFORM depends on the compilation environment. # Even though it is x86_64-linux, the compiled ruby may # be a 32-bit executable. - cpu = [nil].pack('p').size == 4 ? :i386 : :x86_64 - check_proc = Proc.new do |file| - so = MiniSOReader.new(file) - if so.cpu == cpu - true + check_proc = make_proc_to_check_cpu(is_32bit ? :i386 : :x86_64) + when /solaris/ + if is_32bit + @@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH] + if is_big_endian + check_proc = make_proc_to_check_cpu(:sparc) else - puts " skip: #{file} is for #{so.cpu} cpu." - false + check_proc = make_proc_to_check_cpu(:i386) end - end - when /solaris/ - if [0].pack('l!').length == 8 - @@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH] else - @@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH] + @@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH] + if is_big_endian + check_proc = make_proc_to_check_cpu(:sparcv9) + else + check_proc = make_proc_to_check_cpu(:x86_64) + end end when /aix/ oci_glob_postfix = '' @@ -443,29 +442,27 @@ so_ext = 'a' nls_data_ext = 'so' when /hppa.*-hpux/ - if [0].pack('l!').length == 4 + if is_32bit @@ld_envs = %w[SHLIB_PATH] end so_ext = 'sl' when /darwin/ @@ld_envs = %w[DYLD_LIBRARY_PATH] so_ext = 'dylib' - check_proc = Proc.new do |file| - is_32bit = [0].pack('l!').size == 4 - is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102 - if is_32bit - if is_big_endian - this_cpu = :ppc # 32-bit big-endian - else - this_cpu = :i386 # 32-bit little-endian - end + if is_32bit + if is_big_endian + this_cpu = :ppc # 32-bit big-endian else - if is_big_endian - this_cpu = :ppc64 # 64-bit big-endian - else - this_cpu = :x86_64 # 64-bit little-endian - end + this_cpu = :i386 # 32-bit little-endian end + else + if is_big_endian + this_cpu = :ppc64 # 64-bit big-endian + else + this_cpu = :x86_64 # 64-bit little-endian + end + end + check_proc = Proc.new do |file| so = MiniSOReader.new(file) if so.file_format == :universal if so.cpu.include? this_cpu @@ -499,40 +496,43 @@ next end puts " #{env}... " - ENV[env].split(File::PATH_SEPARATOR).each do |path| - next if path.nil? or path == '' - print " checking #{path}... " - path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM - files = Dir.glob(File.join(path, glob_name)) - if files.empty? - puts "no" - next - end - STDOUT.flush - next if (check_proc && !check_proc.call(files[0])) - file = files[0] - ld_path = path - puts "yes" - break - end - break + ld_path, file = check_lib_in_path(ENV[env], glob_name, check_proc) + break if ld_path end - if ld_path.nil? and RUBY_PLATFORM =~ /linux/ - open("|/sbin/ldconfig -p") do |f| - print " checking ld.so.conf... " - STDOUT.flush - while line = f.gets - if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/ - file = "#$1/libclntsh.so.#$2" - path = $1 - next if (check_proc && !check_proc.call(file)) - ld_path = path - puts "yes" - break + if ld_path.nil? + case RUBY_PLATFORM + when /linux/ + open("|/sbin/ldconfig -p") do |f| + print " checking ld.so.conf... " + STDOUT.flush + while line = f.gets + if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/ + file = "#$1/libclntsh.so.#$2" + path = $1 + next if (check_proc && !check_proc.call(file)) + ld_path = path + puts "yes" + break + end end + puts "no" end - puts "no" + when /solaris/ + if is_32bit + crle_cmd = 'crle' + else + crle_cmd = 'crle -64' + end + open('|env LANG=C /usr/bin/' + crle_cmd) do |f| + while line = f.gets + if line =~ /Default Library Path[^:]*:\s*(\S*)/ + puts " checking output of `#{crle_cmd}'... " + ld_path, file = check_lib_in_path($1, glob_name, check_proc) + break + end + end + end end end @@ -549,6 +549,23 @@ nil end + def self.check_lib_in_path(paths, glob_name, check_proc) + paths.split(File::PATH_SEPARATOR).each do |path| + next if path.nil? or path == '' + print " checking #{path}... " + path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM + files = Dir.glob(File.join(path, glob_name)) + if files.empty? + puts "no" + next + end + STDOUT.flush + next if (check_proc && !check_proc.call(files[0])) + puts "yes" + return path, files[0] + end + end + def init check_cc() @cc_is_gcc = check_cc_is_gcc() @@ -1113,20 +1130,8 @@ end if RUBY_PLATFORM =~ /darwin/ - is_intelmac = ([1].pack('s') == "\001\000") - arch_ppc_error = false - arch_i386_error = false open('mkmf.log', 'r') do |f| while line = f.gets - # universal-darwin8.0 (Mac OS X 10.4?) - if line.include? 'cputype (18, architecture ppc) does not match cputype (7)' - # try to link an i386 library but the instant client is ppc. - arch_i386_error = true - end - if line.include? 'cputype (7, architecture i386) does not match cputype (18)' - # try to link a ppc library but the instant client is i386. - arch_ppc_error = true - end if line.include? '/libclntsh.dylib load command 8 unknown cmd field' raise < Revision: 422 Author: kubo Date: 2011-01-30 09:18:54 -0500 (Sun, 30 Jan 2011) Log Message: ----------- * ext/oci8/oraconf.rb: check Oracle client's cpu type on Solaris as on Linux and Mac OS X. change error messages on Mac OS X to suggest to set RC_ARCHS=x86_64 when mkmf.log contains messages such as 'missing required architecture i386 in file.' Modified Paths: -------------- branches/ruby-oci8-2.0/ChangeLog branches/ruby-oci8-2.0/ext/oci8/oraconf.rb Modified: branches/ruby-oci8-2.0/ChangeLog =================================================================== --- branches/ruby-oci8-2.0/ChangeLog 2011-01-30 14:15:18 UTC (rev 421) +++ branches/ruby-oci8-2.0/ChangeLog 2011-01-30 14:18:54 UTC (rev 422) @@ -1,3 +1,9 @@ +2011-01-30 KUBO Takehiro + * ext/oci8/oraconf.rb: check Oracle client's cpu type on Solaris as + on Linux and Mac OS X. change error messages on Mac OS X to suggest + to set RC_ARCHS=x86_64 when mkmf.log contains messages such as + 'missing required architecture i386 in file.' + 2010-12-26 KUBO Takehiro * ext/oci8/ocinumber.c, lib/oci8/bindtype.rb, test/test_oranumber.rb: add OraNumber#has_decimal_part? and OCI8::BindType::BasicNumberType. @@ -68,6 +74,7 @@ 2010-08-15 KUBO Takehiro * ext/oci8/lob.c, ext/oci8/object.c, ext/oci8/oci8.h, lib/oci8/object.rb: support LOB datatypes in Oracle objects. + (reported by Michael Sexton) * ext/oci8/ocihandle.c: fix SEGV in finalizer when temporary LOBs are used. This bug was introduced by the previous commit. Modified: branches/ruby-oci8-2.0/ext/oci8/oraconf.rb =================================================================== --- branches/ruby-oci8-2.0/ext/oci8/oraconf.rb 2011-01-30 14:15:18 UTC (rev 421) +++ branches/ruby-oci8-2.0/ext/oci8/oraconf.rb 2011-01-30 14:18:54 UTC (rev 422) @@ -378,6 +378,18 @@ private + def self.make_proc_to_check_cpu(expect) + Proc.new do |file| + so = MiniSOReader.new(file) + if so.cpu == expect + true + else + puts " skip: #{file} is for #{so.cpu} cpu." + false + end + end + end + def self.check_ic_dir puts "checking for load library path... " STDOUT.flush @@ -390,6 +402,8 @@ so_ext = 'so' nls_data_ext = nil check_proc = nil + is_32bit = [nil].pack('p').size == 4 + is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102 case RUBY_PLATFORM when /mswin32|cygwin|mingw32|bccwin32/ oci_basename = 'oci' @@ -398,44 +412,29 @@ @@ld_envs = %w[PATH] so_ext = 'dll' when /i.86-linux/ - check_proc = Proc.new do |file| - so = MiniSOReader.new(file) - if so.cpu == :i386 - true - else - puts " skip: #{file} is for #{so.cpu} cpu." - false - end - end + check_proc = make_proc_to_check_cpu(:i386) when /ia64-linux/ - check_proc = Proc.new do |file| - so = MiniSOReader.new(file) - if so.cpu == :ia64 - true - else - puts " skip: #{file} is for #{so.cpu} cpu." - false - end - end + check_proc = make_proc_to_check_cpu(:ia64) when /x86_64-linux/ # RUBY_PLATFORM depends on the compilation environment. # Even though it is x86_64-linux, the compiled ruby may # be a 32-bit executable. - cpu = [nil].pack('p').size == 4 ? :i386 : :x86_64 - check_proc = Proc.new do |file| - so = MiniSOReader.new(file) - if so.cpu == cpu - true + check_proc = make_proc_to_check_cpu(is_32bit ? :i386 : :x86_64) + when /solaris/ + if is_32bit + @@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH] + if is_big_endian + check_proc = make_proc_to_check_cpu(:sparc) else - puts " skip: #{file} is for #{so.cpu} cpu." - false + check_proc = make_proc_to_check_cpu(:i386) end - end - when /solaris/ - if [0].pack('l!').length == 8 - @@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH] else - @@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH] + @@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH] + if is_big_endian + check_proc = make_proc_to_check_cpu(:sparcv9) + else + check_proc = make_proc_to_check_cpu(:x86_64) + end end when /aix/ oci_glob_postfix = '' @@ -443,29 +442,27 @@ so_ext = 'a' nls_data_ext = 'so' when /hppa.*-hpux/ - if [0].pack('l!').length == 4 + if is_32bit @@ld_envs = %w[SHLIB_PATH] end so_ext = 'sl' when /darwin/ @@ld_envs = %w[DYLD_LIBRARY_PATH] so_ext = 'dylib' - check_proc = Proc.new do |file| - is_32bit = [0].pack('l!').size == 4 - is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102 - if is_32bit - if is_big_endian - this_cpu = :ppc # 32-bit big-endian - else - this_cpu = :i386 # 32-bit little-endian - end + if is_32bit + if is_big_endian + this_cpu = :ppc # 32-bit big-endian else - if is_big_endian - this_cpu = :ppc64 # 64-bit big-endian - else - this_cpu = :x86_64 # 64-bit little-endian - end + this_cpu = :i386 # 32-bit little-endian end + else + if is_big_endian + this_cpu = :ppc64 # 64-bit big-endian + else + this_cpu = :x86_64 # 64-bit little-endian + end + end + check_proc = Proc.new do |file| so = MiniSOReader.new(file) if so.file_format == :universal if so.cpu.include? this_cpu @@ -499,40 +496,43 @@ next end puts " #{env}... " - ENV[env].split(File::PATH_SEPARATOR).each do |path| - next if path.nil? or path == '' - print " checking #{path}... " - path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM - files = Dir.glob(File.join(path, glob_name)) - if files.empty? - puts "no" - next - end - STDOUT.flush - next if (check_proc && !check_proc.call(files[0])) - file = files[0] - ld_path = path - puts "yes" - break - end - break + ld_path, file = check_lib_in_path(ENV[env], glob_name, check_proc) + break if ld_path end - if ld_path.nil? and RUBY_PLATFORM =~ /linux/ - open("|/sbin/ldconfig -p") do |f| - print " checking ld.so.conf... " - STDOUT.flush - while line = f.gets - if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/ - file = "#$1/libclntsh.so.#$2" - path = $1 - next if (check_proc && !check_proc.call(file)) - ld_path = path - puts "yes" - break + if ld_path.nil? + case RUBY_PLATFORM + when /linux/ + open("|/sbin/ldconfig -p") do |f| + print " checking ld.so.conf... " + STDOUT.flush + while line = f.gets + if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/ + file = "#$1/libclntsh.so.#$2" + path = $1 + next if (check_proc && !check_proc.call(file)) + ld_path = path + puts "yes" + break + end end + puts "no" end - puts "no" + when /solaris/ + if is_32bit + crle_cmd = 'crle' + else + crle_cmd = 'crle -64' + end + open('|env LANG=C /usr/bin/' + crle_cmd) do |f| + while line = f.gets + if line =~ /Default Library Path[^:]*:\s*(\S*)/ + puts " checking output of `#{crle_cmd}'... " + ld_path, file = check_lib_in_path($1, glob_name, check_proc) + break + end + end + end end end @@ -549,6 +549,23 @@ nil end + def self.check_lib_in_path(paths, glob_name, check_proc) + paths.split(File::PATH_SEPARATOR).each do |path| + next if path.nil? or path == '' + print " checking #{path}... " + path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM + files = Dir.glob(File.join(path, glob_name)) + if files.empty? + puts "no" + next + end + STDOUT.flush + next if (check_proc && !check_proc.call(files[0])) + puts "yes" + return path, files[0] + end + end + def init check_cc() @cc_is_gcc = check_cc_is_gcc() @@ -1113,20 +1130,8 @@ end if RUBY_PLATFORM =~ /darwin/ - is_intelmac = ([1].pack('s') == "\001\000") - arch_ppc_error = false - arch_i386_error = false open('mkmf.log', 'r') do |f| while line = f.gets - # universal-darwin8.0 (Mac OS X 10.4?) - if line.include? 'cputype (18, architecture ppc) does not match cputype (7)' - # try to link an i386 library but the instant client is ppc. - arch_i386_error = true - end - if line.include? 'cputype (7, architecture i386) does not match cputype (18)' - # try to link a ppc library but the instant client is i386. - arch_ppc_error = true - end if line.include? '/libclntsh.dylib load command 8 unknown cmd field' raise <