Segfault in Ruby/ODBC

My program is causing a segfault under load, and while I’m going to dig in
to figuring out why, I thought I’d go ahead and see if anyone here could
give me a hand. It appears that the Ruby/ODBC extension is somehow behaving
badly, and not being a C guy, I’d appreciate any help you can give me.

The backtrace below was generated off of an optimized ruby without debugging
info… I may be able to do it again and get better information, but not
immediately. Also, the program itself is large and proprietary, and as with
most SEGFAULTs, I can’t reproduce the problem except with the full program
under load.

The make output:

make[1]: Entering directory
/home/ntalbott/cvs/external-packages/cl-ruby-odbc/cl-ruby-odbc-0.99' gcc -fPIC -Wall -W -I. -I/usr/lib/ruby/1.8/i386-linux -I/usr/lib/ruby/1.8/i386-linux -I. -DHAVE_SQL_H -DHAVE_SQLEXT_H -DHAVE_ODBCINST_H -c odbc.c odbc.c: In functiondsn_new’:
odbc.c:449: warning: unused parameter self' odbc.c: In functiondrv_new’:
odbc.c:474: warning: unused parameter self' odbc.c: In functionsucceeded’:
odbc.c:878: warning: unused parameter m' odbc.c: In functiondbc_raise’:
odbc.c:984: warning: unused parameter self' odbc.c: In functionenv_new’:
odbc.c:1025: warning: type of self' defaults toint’
odbc.c:1033: warning: comparison between signed and unsigned
odbc.c: In function dbc_dsns': odbc.c:1062: warning: unused parameterself’
odbc.c: In function dbc_drivers': odbc.c:1115: warning: unused parameterself’
odbc.c: In function conf_dsn': odbc.c:1191: warning: unused parameterself’
odbc.c: In function dbc_error': odbc.c:1306: warning: unused parameterself’
odbc.c: In function dbc_warn': odbc.c:1312: warning: unused parameterself’
odbc.c: In function dbc_nop': odbc.c:2361: warning: unused parameterself’
odbc.c: In function date_dump': odbc.c:2808: warning: unused parameterdepth’
odbc.c: In function time_dump': odbc.c:3014: warning: unused parameterdepth’
odbc.c: In function timestamp_dump': odbc.c:3255: warning: unused parameterdepth’
odbc.c: In function stmt_hash_mode': odbc.c:4153: warning: unused parameterself’
odbc.c: In function mod_2time': odbc.c:4824: warning: unused parameterself’
odbc.c: In function mod_2date': odbc.c:4930: warning: unused parameterself’
odbc.c: In function mod_trace': odbc.c:4967: warning: unused parameterself’
gcc -shared -L"/usr/lib" -o odbc.so odbc.o -lodbcinst -lodbc -ldl
-lcrypt -lm -lc

The backtrace:

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 28249)]
0x400dd1f5 in mallopt () from /lib/libc.so.6
(gdb) bt
#0 0x400dd1f5 in mallopt () from /lib/libc.so.6
#1 0x400dc383 in malloc () from /lib/libc.so.6
#2 0x0806a48c in ruby_xmalloc ()
#3 0x080a9013 in st_init_table_with_size ()
#4 0x080a904f in st_init_table ()
#5 0x0806c91a in rb_hash ()
#6 0x0806c93c in rb_hash_new ()
#7 0x4077dee5 in _init () from
/usr/lib/ruby/site_ruby/1.8/i386-linux/odbc.so
#8 0x4077eb7e in _init () from
/usr/lib/ruby/site_ruby/1.8/i386-linux/odbc.so
#9 0x4077eeb0 in _init () from
/usr/lib/ruby/site_ruby/1.8/i386-linux/odbc.so
#10 0x0805b99e in rb_with_disable_interrupt ()
#11 0x0805c3f6 in rb_with_disable_interrupt ()
#12 0x0805729f in rb_Array ()
#13 0x080564dc in rb_Array ()
#14 0x080568d5 in rb_Array ()
#15 0x0805bfa9 in rb_with_disable_interrupt ()
#16 0x0805c3f6 in rb_with_disable_interrupt ()
#17 0x0805729f in rb_Array ()
#18 0x0805bfa9 in rb_with_disable_interrupt ()
#19 0x0805c3f6 in rb_with_disable_interrupt ()
#20 0x0805c569 in rb_apply ()
#21 0x0805b99e in rb_with_disable_interrupt ()
#22 0x0805c3f6 in rb_with_disable_interrupt ()
#23 0x0805729f in rb_Array ()
#24 0x080606d7 in rb_f_lambda ()
#25 0x08056364 in rb_Array ()
#26 0x080568d5 in rb_Array ()
#27 0x0805bfa9 in rb_with_disable_interrupt ()
#28 0x0805c3f6 in rb_with_disable_interrupt ()
#29 0x0805729f in rb_Array ()
#30 0x080568d5 in rb_Array ()
#31 0x0805bfa9 in rb_with_disable_interrupt ()
#32 0x0805c3f6 in rb_with_disable_interrupt ()
#33 0x0805729f in rb_Array ()
#34 0x08055dbe in rb_Array ()
#35 0x080568d5 in rb_Array ()
#36 0x08056a80 in rb_Array ()
#37 0x0805bfa9 in rb_with_disable_interrupt ()
#38 0x0805c3f6 in rb_with_disable_interrupt ()
#39 0x0805729f in rb_Array ()
#40 0x080606d7 in rb_f_lambda ()
#41 0x08056364 in rb_Array ()
#42 0x0805bfa9 in rb_with_disable_interrupt ()
#43 0x0805c3f6 in rb_with_disable_interrupt ()
#44 0x0805749c in rb_Array ()
#45 0x080606d7 in rb_f_lambda ()
#46 0x08056364 in rb_Array ()
#47 0x0805bfa9 in rb_with_disable_interrupt ()
#48 0x0805c3f6 in rb_with_disable_interrupt ()
#49 0x0805749c in rb_Array ()
#50 0x080564dc in rb_Array ()
#51 0x0805bfa9 in rb_with_disable_interrupt ()
#52 0x0805c3f6 in rb_with_disable_interrupt ()
#53 0x0805729f in rb_Array ()
#54 0x080564dc in rb_Array ()
#55 0x08059f13 in rb_iterator_p ()
#56 0x08060158 in rb_f_lambda ()
#57 0x080602b5 in rb_f_lambda ()
#58 0x0805b99e in rb_with_disable_interrupt ()
#59 0x0805c3f6 in rb_with_disable_interrupt ()
#60 0x0805729f in rb_Array ()
#61 0x0805bfa9 in rb_with_disable_interrupt ()
#62 0x0805c3f6 in rb_with_disable_interrupt ()
#63 0x0805729f in rb_Array ()
#64 0x08056b64 in rb_Array ()
#65 0x08059f13 in rb_iterator_p ()
#66 0x0805a0f5 in rb_yield ()
#67 0x080c1797 in rb_each ()
#68 0x08059efa in rb_iterator_p ()
#69 0x0805a0f5 in rb_yield ()
#70 0x080b81ee in rb_ary_each ()
#71 0x0805b9d1 in rb_with_disable_interrupt ()
#72 0x0805c3f6 in rb_with_disable_interrupt ()
#73 0x0805c629 in rb_funcall ()
#74 0x080c16a8 in rb_each ()
#75 0x0805a714 in rb_iterate ()
#76 0x080c1801 in rb_each ()
#77 0x0805b99e in rb_with_disable_interrupt ()
#78 0x0805c3f6 in rb_with_disable_interrupt ()
#79 0x0805729f in rb_Array ()
#80 0x080564dc in rb_Array ()
#81 0x08057d9a in rb_Array ()
#82 0x0805bfa9 in rb_with_disable_interrupt ()
#83 0x0805c3f6 in rb_with_disable_interrupt ()
#84 0x0805729f in rb_Array ()
#85 0x08057d9a in rb_Array ()
#86 0x0805bfa9 in rb_with_disable_interrupt ()
#87 0x0805c3f6 in rb_with_disable_interrupt ()
#88 0x0805749c in rb_Array ()
#89 0x0805bfa9 in rb_with_disable_interrupt ()
#90 0x0805c3f6 in rb_with_disable_interrupt ()
#91 0x0805749c in rb_Array ()
#92 0x0805bfa9 in rb_with_disable_interrupt ()
#93 0x0805c3f6 in rb_with_disable_interrupt ()
#94 0x0805c569 in rb_apply ()
#95 0x0805b99e in rb_with_disable_interrupt ()
#96 0x0805c3f6 in rb_with_disable_interrupt ()
#97 0x0805749c in rb_Array ()
#98 0x0805bfa9 in rb_with_disable_interrupt ()
#99 0x0805c3f6 in rb_with_disable_interrupt ()
#100 0x0805729f in rb_Array ()
#101 0x0805bfa9 in rb_with_disable_interrupt ()
#102 0x0805c3f6 in rb_with_disable_interrupt ()
#103 0x0805749c in rb_Array ()
#104 0x080568d5 in rb_Array ()
#105 0x08056a80 in rb_Array ()
#106 0x08056187 in rb_Array ()
#107 0x0805bfa9 in rb_with_disable_interrupt ()
#108 0x0805c3f6 in rb_with_disable_interrupt ()
#109 0x0805749c in rb_Array ()
#110 0x080568d5 in rb_Array ()
#111 0x08056a80 in rb_Array ()
#112 0x08059f13 in rb_iterator_p ()
#113 0x08064b20 in rb_thread_create ()
#114 0x08064894 in rb_thread_stop_timer ()
#115 0x08064c0e in rb_thread_create ()
#116 0x0805b99e in rb_with_disable_interrupt ()
#117 0x0805c3f6 in rb_with_disable_interrupt ()
#118 0x0805729f in rb_Array ()
#119 0x080564dc in rb_Array ()
#120 0x0805bfa9 in rb_with_disable_interrupt ()
#121 0x0805c3f6 in rb_with_disable_interrupt ()
#122 0x0805749c in rb_Array ()
#123 0x080606d7 in rb_f_lambda ()
#124 0x08056364 in rb_Array ()
#125 0x08057df7 in rb_Array ()
#126 0x08059f13 in rb_iterator_p ()
#127 0x0805a0f5 in rb_yield ()
#128 0x080b81ee in rb_ary_each ()
#129 0x0805b9d1 in rb_with_disable_interrupt ()
#130 0x0805c3f6 in rb_with_disable_interrupt ()
#131 0x0805729f in rb_Array ()
#132 0x080564dc in rb_Array ()
#133 0x080568d5 in rb_Array ()
#134 0x08056187 in rb_Array ()
#135 0x08059f13 in rb_iterator_p ()
#136 0x08056842 in rb_Array ()
#137 0x0805bfa9 in rb_with_disable_interrupt ()
#138 0x0805c3f6 in rb_with_disable_interrupt ()
#139 0x0805729f in rb_Array ()
#140 0x080564dc in rb_Array ()
#141 0x0805bfa9 in rb_with_disable_interrupt ()
#142 0x0805c3f6 in rb_with_disable_interrupt ()
#143 0x0805729f in rb_Array ()
#144 0x0805bfa9 in rb_with_disable_interrupt ()
#145 0x0805c3f6 in rb_with_disable_interrupt ()
#146 0x0805729f in rb_Array ()
#147 0x0805bfa9 in rb_with_disable_interrupt ()
#148 0x0805c3f6 in rb_with_disable_interrupt ()
#149 0x0805750c in rb_Array ()
#150 0x0805bfa9 in rb_with_disable_interrupt ()
#151 0x0805c3f6 in rb_with_disable_interrupt ()
#152 0x0805c569 in rb_apply ()
#153 0x0805b99e in rb_with_disable_interrupt ()
#154 0x0805c3f6 in rb_with_disable_interrupt ()
#155 0x0805749c in rb_Array ()
#156 0x0805bfa9 in rb_with_disable_interrupt ()
#157 0x0805c3f6 in rb_with_disable_interrupt ()
#158 0x0805729f in rb_Array ()
#159 0x08053460 in ruby_init ()
#160 0x0805392e in ruby_exec ()
#161 0x0805398a in ruby_run ()
#162 0x08051e62 in main ()
#163 0x40080db6 in __libc_start_main () from /lib/libc.so.6
(gdb)
(gdb) c
Continuing.
/usr/lib/ruby/site_ruby/1.8/DBD/ODBC/ODBC.rb:124: [BUG] Segmentation fault
ruby 1.8.1 (2003-10-31) [i386-linux]

Program received signal SIGABRT, Aborted.
0x400945f1 in kill () from /lib/libc.so.6

If more info would help, let me know and I’ll try to provide it.

Thanks for any help you can give!

Nathaniel

<:((><

Hi,

···

From: “Nathaniel Talbott” nathaniel@NOSPAMtalbott.ws
Subject: Segfault in Ruby/ODBC
Date: Sat, 8 Nov 2003 07:08:25 +0900
Message-ID: 013501c3a57b$835ee2a0$c81e140a@abraham

My program is causing a segfault under load, and while I’m going to dig in
to figuring out why, I thought I’d go ahead and see if anyone here could
give me a hand. It appears that the Ruby/ODBC extension is somehow behaving
badly, and not being a C guy, I’d appreciate any help you can give me.

I don’t know Ruby/ODBC, but I think that your trouble is similar
to the trouble on Ruby/Tk with pthread-enabled Tck/Tk libraries.
I worked to fix the Ruby/Tk problem last week, and added
‘–with-pthead-ext’ to configure options. If your trouble depends
on the same part of Ruby core, the option may help you.

                              Hidetoshi NAGAI (nagai@ai.kyutech.ac.jp)

OK, I have better data now. First of all, I have a small program that will
reproduce the problem, provided you have access to an odbc database:

require ‘dbi’

threads =
Thread.abort_on_exception = true
10.times do |i|
threads << Thread.new do
db = DBI::connect(“dbi:ODBC:dbname”, “user”, “password”)
loop do
p “Looping #{i}…”
db.tables
db.execute(“SELECT COUNT(*) FROM table”).finish
db.tables
db.execute(“SELECT * FROM table”).finish
end
end
end
threads.each{|t| t.join}

Obviously you’d need to replace dbname, user, password and table with things
that make sense for your setup. I’m using unixODBC to connect via FreeTDS to
a MSSQL server on a Windows NT box.

Also, I’ve recompiled Ruby and the odbc driver with debugging information,
and have a better backtrace:

(gdb) run
Starting program: /usr/bin/ruby t.rb
[New Thread 16384 (LWP 16080)]
“Looping 0…”
“Looping 2…”
“Looping 1…”

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 16080)]
0x400de1f5 in mallopt () from /lib/libc.so.6
(gdb) bt
#0 0x400de1f5 in mallopt () from /lib/libc.so.6
#1 0x400dd383 in malloc () from /lib/libc.so.6
#2 0x08070cf6 in ruby_xmalloc (size=16) at gc.c:108
#3 0x080bf370 in st_init_table_with_size (type=0x81000dc, size=11) at
st.c:167
#4 0x080bf3c8 in st_init_table (type=0x81000dc) at st.c:180
#5 0x08073c87 in hash_alloc (klass=1075592068) at hash.c:188
#6 0x08073cb8 in rb_hash_new () at hash.c:196
#7 0x4022ec69 in do_fetch (q=0x819d6d0, mode=1) at odbc.c:3802
#8 0x4022fce4 in stmt_fetch_hash1 (argc=1, argv=0xbfffabb0,
self=1075690112, bang=0)
at odbc.c:4206
#9 0x40230106 in stmt_each_hash (argc=0, argv=0x0, self=1075690112) at
odbc.c:4345
#10 0x0806adb3 in call_cfunc (func=0x40230030 <stmt_each_hash>,
recv=1075690112, len=-1, argc=0,
argv=0x0) at eval.c:4841
#11 0x0805dc43 in rb_call0 (klass=1075735712, recv=1075690112, id=14073,
oid=14073, argc=0,
argv=0x0, body=0x401e2164, nosuper=0) at eval.c:4975
#12 0x0805e788 in rb_call (klass=1075735712, recv=1075690112, mid=14073,
argc=0, argv=0x0, scope=0)
at eval.c:5196
#13 0x0805866a in rb_eval (self=1075693732, n=0x401f75a0) at eval.c:3026
#14 0x08057438 in rb_eval (self=1075693732, n=0x401f7a78) at eval.c:2753
#15 0x08057979 in rb_eval (self=1075693732, n=0x401f6204) at eval.c:2839
#16 0x0805e23f in rb_call0 (klass=1075705512, recv=1075693732, id=10217,
oid=10217, argc=0,
argv=0x0, body=0x401f6204, nosuper=0) at eval.c:5103
#17 0x0805e788 in rb_call (klass=1075705512, recv=1075693732, mid=10217,
argc=0, argv=0x0, scope=0)
at eval.c:5196
#18 0x0805866a in rb_eval (self=1075695672, n=0x401ab2dc) at eval.c:3026
#19 0x0805e23f in rb_call0 (klass=1075842852, recv=1075695672, id=10217,
oid=10217, argc=0,
argv=0x0, body=0x401ab2dc, nosuper=0) at eval.c:5103
#20 0x0805e788 in rb_call (klass=1075842852, recv=1075695672, mid=10217,
argc=0, argv=0x0, scope=0)
at eval.c:5196
#21 0x0805866a in rb_eval (self=1075620448, n=0x401baf98) at eval.c:3026
#22 0x0805c050 in rb_yield_0 (val=6, self=1075620448, klass=0, flags=0,
avalue=0) at eval.c:4229
#23 0x0805c432 in rb_f_loop () at eval.c:4330
#24 0x0806adcd in call_cfunc (func=0x805c418 <rb_f_loop>, recv=1075620448,
len=0, argc=0, argv=0x0)
at eval.c:4844
#25 0x0805dc43 in rb_call0 (klass=1075625128, recv=1075620448, id=3921,
oid=3921, argc=0,
argv=0x0, body=0x401ca1a0, nosuper=0) at eval.c:4975
#26 0x0805e788 in rb_call (klass=1075625128, recv=1075620448, mid=3921,
argc=0, argv=0x0, scope=1)
at eval.c:5196
#27 0x08058924 in rb_eval (self=1075620448, n=0x401bad7c) at eval.c:3041
#28 0x08057438 in rb_eval (self=1075620448, n=0x401bad04) at eval.c:2753
#29 0x0805c050 in rb_yield_0 (val=1075838972, self=1075620448, klass=0,
flags=2, avalue=2)
at eval.c:4229
#30 0x08068e60 in rb_thread_yield (arg=1075838972, th=0x816efd8) at
eval.c:9581
#31 0x08068b04 in rb_thread_start_0 (fn=0x8068d94 <rb_thread_yield>,
arg=0x401ffffc, th=0x816efd8)
at eval.c:9495
#32 0x08068f53 in rb_thread_initialize (thread=1075839612,
args=1075838972) at eval.c:9610
#33 0x0806ad94 in call_cfunc (func=0x8068f04 <rb_thread_initialize>,
recv=1075839612, len=-2,
argc=0, argv=0x0) at eval.c:4838
#34 0x0805dc43 in rb_call0 (klass=1075609928, recv=1075839612, id=2953,
oid=2953, argc=0,
argv=0x0, body=0x401c80e4, nosuper=0) at eval.c:4975
#35 0x0805e788 in rb_call (klass=1075609928, recv=1075839612, mid=2953,
argc=0, argv=0x0, scope=1)
at eval.c:5196
#36 0x0805e9ba in rb_funcall2 (recv=1075839612, mid=2953, argc=0,
argv=0x0) at eval.c:5271
#37 0x0806124c in rb_obj_call_init (obj=1075839612, argc=0, argv=0x0) at
eval.c:6341
#38 0x08068eb4 in rb_thread_s_new (argc=0, argv=0x0, klass=1075609928) at
eval.c:9594
#39 0x0806adb3 in call_cfunc (func=0x8068e74 <rb_thread_s_new>,
recv=1075609928, len=-1, argc=0,
argv=0x0) at eval.c:4841
#40 0x0805dc43 in rb_call0 (klass=1075609908, recv=1075609928, id=3353,
oid=3353, argc=0,
argv=0x0, body=0x401c810c, nosuper=0) at eval.c:4975
#41 0x0805e788 in rb_call (klass=1075609908, recv=1075609928, mid=3353,
argc=0, argv=0x0, scope=0)
at eval.c:5196
#42 0x0805866a in rb_eval (self=1075620448, n=0x401bb254) at eval.c:3026
#43 0x08057438 in rb_eval (self=1075620448, n=0x401bacf0) at eval.c:2753
#44 0x08058506 in rb_eval (self=1075620448, n=0x401bacb4) at eval.c:3021
#45 0x0805c050 in rb_yield_0 (val=1, self=1075620448, klass=0, flags=0,
avalue=0) at eval.c:4229
#46 0x0805c306 in rb_yield (val=1) at eval.c:4282
#47 0x08087af3 in int_dotimes (num=21) at numeric.c:1775
#48 0x0806adcd in call_cfunc (func=0x8087aac <int_dotimes>, recv=21,
len=0, argc=0, argv=0x0)
at eval.c:4844
#49 0x0805dc43 in rb_call0 (klass=1075606888, recv=21, id=5385, oid=5385,
argc=0, argv=0x0,
body=0x401c74a0, nosuper=0) at eval.c:4975
#50 0x0805e788 in rb_call (klass=1075606888, recv=21, mid=5385, argc=0,
argv=0x0, scope=0)
at eval.c:5196
#51 0x0805866a in rb_eval (self=1075620448, n=0x401bb2e0) at eval.c:3026
#52 0x08057438 in rb_eval (self=1075620448, n=0x401bb3bc) at eval.c:2753
#53 0x08053a80 in eval_node (self=1075620448, node=0x401bb3bc) at
eval.c:1217
#54 0x0805408a in ruby_exec () at eval.c:1387
#55 0x0805410d in ruby_run () at eval.c:1408
#56 0x08051f93 in main (argc=2, argv=0xbffff704, envp=0xbffff710) at
main.c:50
(gdb) c
Continuing.
/usr/lib/ruby/site_ruby/1.8/DBD/ODBC/ODBC.rb:124: [BUG] Segmentation fault
ruby 1.8.1 (2003-10-31) [i386-linux]

Program received signal SIGABRT, Aborted.
0x400955f1 in kill () from /lib/libc.so.6

I’m going to dig in to this and see if I can figure out what the problem is,
but any help would be appreciated. Let me know if there’s any more
information I can provide that would be useful.

Thanks,

Nathaniel

<:((><

···

Nathaniel Talbott [mailto:nathaniel@NOSPAMtalbott.ws] wrote:

My program is causing a segfault under load, and while I’m
going to dig in to figuring out why, I thought I’d go ahead
and see if anyone here could give me a hand. It appears that
the Ruby/ODBC extension is somehow behaving badly, and not
being a C guy, I’d appreciate any help you can give me.

The backtrace below was generated off of an optimized ruby
without debugging info… I may be able to do it again and
get better information, but not immediately. Also, the
program itself is large and proprietary, and as with most
SEGFAULTs, I can’t reproduce the problem except with the full
program under load.

Thanks for the reply! A few questions:

  • How do I use the --with-pthread-ext configure option?
    Do I pass it to extconf.rb for the extension? Or do I
    need to enable it when I compile Ruby?

  • Is this option available under 1.8.1-preview2? Or do
    I need to use the most recent CVS?

Thanks,

Nathaniel

<:((><

···

Hidetoshi NAGAI [mailto:nagai@ai.kyutech.ac.jp] wrote:

From: “Nathaniel Talbott” nathaniel@NOSPAMtalbott.ws
Subject: Segfault in Ruby/ODBC
Date: Sat, 8 Nov 2003 07:08:25 +0900
Message-ID: 013501c3a57b$835ee2a0$c81e140a@abraham

My program is causing a segfault under load, and while I’m going to
dig in to figuring out why, I thought I’d go ahead and see
if anyone
here could give me a hand. It appears that the Ruby/ODBC
extension is
somehow behaving badly, and not being a C guy, I’d
appreciate any help
you can give me.

I don’t know Ruby/ODBC, but I think that your trouble is similar
to the trouble on Ruby/Tk with pthread-enabled Tck/Tk libraries.
I worked to fix the Ruby/Tk problem last week, and added
‘–with-pthead-ext’ to configure options. If your trouble depends
on the same part of Ruby core, the option may help you.

  #7 0x4022ec69 in do_fetch (q=0x819d6d0, mode=1) at odbc.c:3802

If I'm right the problem is not in ruby but in do_fetch() (memory
problem).

Guy Decoux

I never thought it was in Ruby… I’ll dig in to do_fetch and see if I can
find the memory problem. Any help from the resident C gurus would be
appreciated :slight_smile:

Thanks,

Nathaniel

<:((><

···

ts [mailto:decoux@moulon.inra.fr] wrote:

If I’m right the problem is not in ruby but in do_fetch()
(memory problem).

Hi,

···

From: “Nathaniel Talbott” nathaniel@NOSPAMtalbott.ws
Subject: Re: Segfault in Ruby/ODBC
Date: Mon, 10 Nov 2003 22:48:34 +0900
Message-ID: 003701c3a791$2e582150$c81e140a@abraham

Thanks for the reply! A few questions:

  • How do I use the --with-pthread-ext configure option?
    Do I pass it to extconf.rb for the extension? Or do I
    need to enable it when I compile Ruby?

When enable ‘–with-pthread-ext’, for example, ‘pthread_mutex_lock’
is added to rb_thread_schedule() function on eval.c. That is, you
must re-configure and re-compile Ruby.

Please pay attention to the patch for tcltklib.c.

To fix the problem, I had to edit the source file as only one

ruby-thread can call Tcl/Tk’s internal functions.

  • Is this option available under 1.8.1-preview2? Or do
    I need to use the most recent CVS?

Please try the most recent CVS.
The last change for ‘–with-pthread-ext’ option was adopted at
2003/11/08 13:49:50 JST.

                                     永井 秀利 (九工大 知能情報)
                                         nagai@ai.kyutech.ac.jp

OK, I’m pretty sure I’ve fixed the problem… for anyone who’s interested,
I’ve included a patch with all of my changes to odbc.c.

Turns out the problem lay in one of the underlying library functions
(SQLColAttributes) claiming to return a zero-length string when the
requested value (SQL_COLUMN_TABLE_NAME) didn’t exist, but instead not
returning anything, leaving the buffer the value was supposed to be put in
to in a hosed state. I’ve fixed it for the time being by making sure the
buffer always starts with a NULL value, so that it will always be
interpreted as an empty string if the function doesn’t do anything to it. I
don’t know if this will work if the extension is built with unicode support,
but since I don’t have to deal with that environment, I don’t really care at
this point. If there’s a better solution, I’m all ears.

Thanks for all your help,

Nathaniel

<:((><

— …/odbc.c.old Thu Aug 21 14:44:37 2003
+++ odbc.c Mon Nov 10 12:51:05 2003
@@ -1021,7 +1021,7 @@
*/

static VALUE
-env_new(self)
+env_new(VALUE self)
{
ENV *e;
SQLHENV henv = SQL_NULL_HENV;
@@ -1904,6 +1904,7 @@
char name[SQL_MAX_MESSAGE_LENGTH];
#endif

  • name[0] = 0;
    if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
    SQLColAttributes(hstmt, ic, SQL_COLUMN_LABEL, name,
    (SQLSMALLINT) sizeof (name),
    @@ -1940,6 +1941,7 @@
    rb_iv_set(obj, “@name”, rb_tainted_str_new2(upcase_if(name, upc)));
    #endif
    v = Qnil;

  • name[0] = 0;
    if (succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, hstmt,
    SQLColAttributes(hstmt, ic, SQL_COLUMN_TABLE_NAME, name,
    (SQLSMALLINT) sizeof (name),
    @@ -3713,6 +3715,7 @@
    #endif

    for (i = 0; i < q->ncols; i++) {

  •            name[0] = 0;
      if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
      	       SQLColAttributes(q->hstmt,
      				(SQLUSMALLINT) (i + 1),
    

@@ -3730,6 +3733,7 @@
#else
need += 2 * (strlen(name) + 1);
#endif

  •            name[0] = 0;
      if (!succeeded(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
      	       SQLColAttributes(q->hstmt,
      				(SQLUSMALLINT) (i + 1),
    

@@ -3757,6 +3761,7 @@
for (i = 0; i < q->ncols; i++) {
char *p0;

  •            name[0] = 0;
      tracesql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
      	 SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1),
      			  SQL_COLUMN_TABLE_NAME, name,
    

@@ -3771,6 +3776,7 @@
strcat(p, “.”);
p += strlen(p);
p0 = p;

  •            name[0] = 0;
      tracesql(SQL_NULL_HENV, SQL_NULL_HDBC, q->hstmt,
      	 SQLColAttributes(q->hstmt, (SQLUSMALLINT) (i + 1),
      			  SQL_COLUMN_LABEL, name,
    

@@ -5426,8 +5432,11 @@
rb_define_method(Cproc, “initialize”, stmt_proc_init, -1);
rb_define_method(Cproc, “call”, stmt_proc_call, -1);
rb_define_method(Cproc, “”, stmt_proc_call, -1);

···

Nathaniel Talbott [mailto:nathaniel@NOSPAMtalbott.ws] wrote:

I’ll dig in to do_fetch and
see if I can find the memory problem.

+#ifndef HAVE_RB_DEFINE_ALLOC_FUNC
rb_enable_super(Cproc, “call”);
rb_enable_super(Cproc, “”);
+#endif

 /* constants */
 for (i = 0; o_const[i].name != NULL; i++) {