Permalink
Browse files

Work around segfault in rb_ary_store during extension initialization,…

… bump version to 1.0.3

I've only seen this segfault when running Sequel's default rake
task with home_run loaded on OpenBSD amd64.  Even though rb_ary_push
is given the correct arguments, a segfault still occurs in
rb_ary_store.  Unfortunately, it doesn't happen if you build ruby in
debug mode, so I can't tell why it occurs.  My best guess is it is
due to an unforunate interaction between ruby and OpenBSD malloc
which only happens on amd64 and only when memory happens to be laid
out a certain way.

This commit avoids the issue by using rb_ary_new4 and a temporary
C array instead of using a blank ruby array and rb_ary_push to add
items to it.  I also tried increasing the integer passed to
rb_ary_new2 as well as using rb_ary_new instead of rb_ary_new2,
which seemed to reduce the frequency of the error, but not
eliminate it completely.
  • Loading branch information...
1 parent f2f33c0 commit 9c264acdf851cbecc314ffe0e27ef40de4e43220 @jeremyevans committed Jul 5, 2011
Showing with 20 additions and 12 deletions.
  1. +5 −1 CHANGELOG
  2. +14 −10 ext/date_ext/date_ext.c
  3. +1 −1 home_run.gemspec
View
@@ -1,3 +1,7 @@
+=== 1.0.3 (2011-07-05)
+
+* Work around segfault in rb_ary_push during extension initialization (jeremyevans)
+
=== 1.0.2 (2011-03-18)
* Support fractional timestamps in the ISO date parser (funny-falcon)
@@ -12,7 +16,7 @@
=== 1.0.0 (2011-02-01)
-* Define the ZONES hash in ruby to work around probably interpreter bug (jeremyevans)
+* Define the ZONES hash in ruby to work around probable interpreter bug (jeremyevans)
=== 0.9.4 (2010-10-18)
@@ -4011,6 +4011,10 @@ static VALUE rhrd_s_valid_time_q(VALUE klass, VALUE rh, VALUE rm, VALUE rs) {
* */
void Init_date_ext(void) {
int i;
+ VALUE monthnames[13];
+ VALUE abbr_monthnames[13];
+ VALUE daynames[7];
+ VALUE abbr_daynames[7];
/* Setup static IDs and symbols */
@@ -4165,21 +4169,21 @@ void Init_date_ext(void) {
/* Setup static constants */
- rhrd_monthnames = rb_ary_new2(13);
- rhrd_abbr_monthnames = rb_ary_new2(13);
- rb_ary_push(rhrd_monthnames, Qnil);
- rb_ary_push(rhrd_abbr_monthnames, Qnil);
+ monthnames[0] = Qnil;
+ abbr_monthnames[0] = Qnil;
for(i = 1; i < 13; i++) {
- rb_ary_push(rhrd_monthnames, rb_str_new2((const char *)rhrd__month_names[i]));
- rb_ary_push(rhrd_abbr_monthnames, rb_str_new2(rhrd__abbr_month_names[i]));
+ monthnames[i] = rb_str_new2((const char *)rhrd__month_names[i]);
+ abbr_monthnames[i] = rb_str_new2(rhrd__abbr_month_names[i]);
}
+ rhrd_monthnames = rb_ary_new4(13, monthnames);
+ rhrd_abbr_monthnames = rb_ary_new4(13, abbr_monthnames);
- rhrd_daynames = rb_ary_new2(7);
- rhrd_abbr_daynames = rb_ary_new2(7);
for(i = 0; i < 7; i++) {
- rb_ary_push(rhrd_daynames, rb_str_new2(rhrd__day_names[i]));
- rb_ary_push(rhrd_abbr_daynames, rb_str_new2(rhrd__abbr_day_names[i]));
+ daynames[i] = rb_str_new2(rhrd__day_names[i]);
+ abbr_daynames[i] = rb_str_new2(rhrd__abbr_day_names[i]);
}
+ rhrd_daynames = rb_ary_new4(7, daynames);
+ rhrd_abbr_daynames = rb_ary_new4(7, abbr_daynames);
rhrd_start_num = LONG2NUM(RHR_JD_MIN - 1);
rhrd_empty_string = rb_str_new("", 0);
View
@@ -1,6 +1,6 @@
HOME_RUN_GEMSPEC = Gem::Specification.new do |s|
s.name = 'home_run'
- s.version = '1.0.2'
+ s.version = '1.0.3'
s.platform = Gem::Platform::RUBY
s.has_rdoc = true
s.extra_rdoc_files = ["README.rdoc", "CHANGELOG", "LICENSE"]

0 comments on commit 9c264ac

Please sign in to comment.