Fix for segfault in RubyChildInitHandler
Michael Granger <[email protected]> Fri, 26 May 2006 18:00:36 -0700
| Newsgroups | gmane.comp.apache.mod-ruby |
|---|---|
| Message-ID | <[email protected]> |
--Apple-Mail-4-733228603
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
delsp=yes;
format=flowed
The most recent mod_ruby (rev 125) segfaults when a
RubyChildInitHandler is configured. Here is a minimal httpd.conf
testcase that can be run from the working directory:
#
# Minimal RubyChildInitHandler testcase
#
ServerRoot "."
LoadModule ruby_module ./mod_ruby.so
PidFile testserver.pid
ErrorLog test.error_log
LogLevel debug
DocumentRoot "doc"
Listen 8888
RubyChildInitHandler "class CIHandler; def child_init(r); return
Apache::OK; end; end; CIHandler.new"
Starting the server on MacOS/X with Apache 2.2.x (prefork mpm) does
this:
$ httpd -d . -f minimal.conf -e debug -X
[Fri May 26 17:26:27 2006] [debug] mod_so.c(246): loaded module
ruby_module
Abort trap
With the following stacktrace:
Exception: EXC_BAD_ACCESS (0x0001)
Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000014
Thread 0 Crashed:
0 mod_ruby.so 0x0111e1d8 apache_request_new + 248 (request.c:195)
1 mod_ruby.so 0x01118948 ruby_handler_internal + 440
(mod_ruby.c:1130)
2 mod_ruby.so 0x01118d48 ruby_handler + 212 (mod_ruby.c:1329)
3 httpd 0x0000a8fc ap_run_child_init + 112 (config.c:153)
4 httpd 0x00029424 child_main + 324 (prefork.c:515)
5 httpd 0x00029890 make_child + 136 (prefork.c:680)
6 httpd 0x00029ebc ap_mpm_run + 1172 (prefork.c:956)
7 httpd 0x00003e00 main + 3228 (main.c:712)
8 httpd 0x00002630 _start + 344 (crt.c:272)
9 httpd 0x000024d4 start + 60
This is caused by apache_request_new() trying to build the per-
directory options array:
if (dconf->gc_per_request)
Because the request is a fake one from fake_request_rec() in
mod_ruby.c:842, r->dconf is 0x00, and so segfaults when accessed.
I discovered a similar situation in mod_ruby.c:1180 at the very end
of per_request_cleanup():
if (dconf->gc_per_request)
The attached patch works around these two situations by adding guard
conditionals around code that uses dconf, but I'm not sure if it's
the best way to do this.
I hereby transfer the rights to any and all code in this email to
Shugo-san.
--Apple-Mail-4-733228603
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
x-unix-mode=0644;
name="child_init_handler_fix.patch"
Content-Disposition: attachment;
filename=child_init_handler_fix.patch
Index: mod_ruby.c
===================================================================
--- mod_ruby.c (revision 125)
+++ mod_ruby.c (working copy)
@@ -1177,7 +1177,7 @@
restore_env(r->pool, rconf->saved_env);
}
rb_progname = Qnil;
- if (dconf->gc_per_request)
+ if (dconf && dconf->gc_per_request)
rb_gc();
}
Index: request.c
===================================================================
--- request.c (revision 125)
+++ request.c (working copy)
@@ -192,14 +192,16 @@
data->cookies = rb_hash_new();
data->param_table = Qnil;
data->options = rb_hash_new();
- opts_arr = apr_table_elts(dconf->options);
- opts = (table_entry *) opts_arr->elts;
- for (i = 0; i < opts_arr->nelts; i++) {
- if (opts[i].key == NULL)
- continue;
- rb_hash_aset(data->options,
- rb_tainted_str_new2(opts[i].key),
- rb_tainted_str_new2(opts[i].val));
+ if (dconf) {
+ opts_arr = apr_table_elts(dconf->options);
+ opts = (table_entry *) opts_arr->elts;
+ for (i = 0; i < opts_arr->nelts; i++) {
+ if (opts[i].key == NULL)
+ continue;
+ rb_hash_aset(data->options,
+ rb_tainted_str_new2(opts[i].key),
+ rb_tainted_str_new2(opts[i].val));
+ }
}
rb_apache_register_object(obj);
--Apple-Mail-4-733228603
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
charset=US-ASCII;
format=flowed
--
Michael Granger <[email protected]>
Rubymage, Architect, Believer
The FaerieMUD Consortium <http://www.faeriemud.org/>
--Apple-Mail-4-733228603--