mod_speedycgi2 on Apache 2.2

SpeedyCGI を使ってみようと思って cpan install CGI::SpeedyCGI したら,怒られました。のであれこれ調べてなんとか動くパッチを作ってみました。

原因は Apache 2.2 (APR-1.2) になって,

  • APR_BRIGADE_FOREACH() というマクロが deprecated になった(参考
  • apr_filename_of_pathname という関数が apr_filepath_name_get になった(CHANGES-APR-1.2

という非互換性があるためでした。

でも CGI::SpeedyCGI は Perl 5.8.6 以降ではメモリリークする(RT#13521)罠。がーん。speedycgi with Perl 5.8.6 のメモリリークをなおした - daily dayflower 参照

以下,パッチです。

--- mod_speedycgi2/mod_speedycgi2.c.orig	2006-12-05 16:50:31.162344855 +0900
+++ mod_speedycgi2/mod_speedycgi2.c	2006-12-05 17:15:17.897326783 +0900
@@ -340,14 +340,14 @@
     const char *buf;
     apr_size_t len;
     apr_status_t rv;
-    APR_BRIGADE_FOREACH(e, bb) {
-        if (APR_BUCKET_IS_EOS(e)) {
-            break;
-        }
+    /* broke down deprecated APR_BRIGADE_FOREACH() macro */
+    e = APR_BRIGADE_FIRST(bb);
+    while (e != APR_BRIGADE_SENTINEL(bb) && ! APR_BUCKET_IS_EOS(e)) {
         rv = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ);
         if (rv != APR_SUCCESS) {
             break;
         }
+        e = APR_BUCKET_NEXT(e);
     }
 }
 
@@ -380,7 +380,7 @@
         return DECLINED;
     }
 
-    argv0 = apr_filename_of_pathname(r->filename);
+    argv0 = apr_filepath_name_get(r->filename);
     nph = !(strncmp(argv0, "nph-", 4));
 
     if (!(ap_allow_options(r) & OPT_EXECCGI) && !is_scriptaliased(r))
@@ -436,7 +436,7 @@
     if ((rv = default_build_command(&command, &argv, r, p)) != APR_SUCCESS) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rv, r,
                       "don't know how to spawn child process: %s", 
-                      apr_filename_of_pathname(r->filename));
+                      apr_filepath_name_get(r->filename));
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -445,7 +445,7 @@
                             command, argv, r, p)) != APR_SUCCESS) {
         ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_TOCLIENT, rv, r,
                       "couldn't spawn child process: %s",
-		      apr_filename_of_pathname(r->filename));
+		      apr_filepath_name_get(r->filename));
         return HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -465,7 +465,10 @@
             return rv;
         }
 
-        APR_BRIGADE_FOREACH(bucket, bb) {
+        /* broke down deprecated APR_BRIGADE_FOREACH() macro */
+        for (bucket = APR_BRIGADE_FIRST(bb);
+             bucket != APR_BRIGADE_SENTINEL(bb);
+             bucket = APR_BUCKET_NEXT(bucket)) {
             const char *data;
             apr_size_t len;
 

簡単な CGI を実行して speedy_backend が立ち上がるところまではたしかめました。でもこのバックエンドプロセス,殺すときはどうすればいいんでしょう。普通に killall でいいのかな。