Hi, So far, I really like mod_python -- it's a great piece of software. But I think I've found a small bug.
I've noticed that adding a handler using add_handler prompts apache to segfault if no statically registered (e.g., specified in the apache conf files) handlers of the same category (e.g., PythonLogHandler, PythonTransHandler) are present. I've tested this in both the release version (314) and version 325b (albeit more thoroughly in the former). Here's how I triggered the bug: Add this to apache2.conf: PythonPath "sys.path+[(the path goes here)]" PythonTransHandler crashbug crashbug.py contains: from mod_python import apache def transhandler(req): req.add_handler("PythonLogHandler","foo::loghandler") return apache.OK foo contains: from mod_python import apache def loghandler(req): import sys sys.stderr.write("foo: saw request type:" + req.method + "\n") return apache.OK If I run apache sudo /usr/sbin/apache2 -X and tickle the server: echo -e "GET / HTTP/1.0\n\n" | nc localhost 8080 ...apache segfaults. On the other hand, if I add the line PythonLogHandler notfoo to apache2.conf, where notfoo.py is identical to foo except that "foo:" is replaced with "notfoo", I get the expected two lines in the log, and no crash. Here's the trace: Program received signal SIGSEGV, Segmentation fault. [Switching to Thread -1214269216 (LWP 21283)] 0xb76dddb3 in hlist_copy (p=0x8158fa8, hle=0x0) at hlist.c:91 91 head->handler = apr_pstrdup(p, hle->handler); (gdb) bt #0 0xb76dddb3 in hlist_copy (p=0x8158fa8, hle=0x0) at hlist.c:91 #1 0xb76dd9aa in MpHList_FromHLEntry (hle=0x0) at hlistobject.c:49 #2 0xb76e59b6 in python_handler (req=0x8238480, phase=0xb76e804c "PythonLogHandler") at mod_python.c:1029 #3 0x08086086 in ap_run_log_transaction () #4 0x0806963e in ap_process_request () #5 0x08064b19 in _start () I suspect the problem is in this part of mod_python.c: Here's my understanding (please correct me if I'm wrong). If hle is NULL (i.e., there were no handlers of this type registered in the apache conf), but dynhle is not null (we registered a dynamic handler), we continue processing... if (! (hle || dynhle)) { /* nothing to do here */ return DECLINED; } /* determine interpreter to use */ interp_name = select_interp_name(req, NULL, conf, hle, NULL, 0); /* get/create interpreter */ idata = get_interpreter(interp_name, req->server); if (!idata) return HTTP_INTERNAL_SERVER_ERROR; /* create/acquire request object */ request_obj = get_request_object(req, interp_name, phase); /* remember the extension if any. used by publisher */ if (ext) request_obj->extension = apr_pstrdup(req->pool, ext); But then, we try to create an MpHList from hle, which is NULL -- prompting a crash a few levels down. /* create a hahdler list object */ request_obj->hlo = (hlistobject *)MpHList_FromHLEntry(hle); Here's how I fixed it: --- /home/jdb/dl/mpsvn/mod_python-3.1.4/src/mod_python.c 2005-01-29 16:25:28.000000000 -0500 +++ mod_python.c 2006-01-04 16:59:13.000000000 -0500 @@ -1026,13 +1026,18 @@ request_obj->extension = apr_pstrdup(req->pool, ext); /* create a hahdler list object */ - request_obj->hlo = (hlistobject *)MpHList_FromHLEntry(hle); - - /* add dynamically registered handlers, if any */ - if (dynhle) { + if (hle) { + request_obj->hlo = (hlistobject *)MpHList_FromHLEntry(hle); + /* add dynamically registered handlers, if any */ + if (dynhle) { MpHList_Append(request_obj->hlo, dynhle); + } } - + else { + /* hle was NULL; so create hlo from dynhle */ + request_obj->hlo = (hlistobject *)MpHList_FromHLEntry(dynhle); + } + /* * Here is where we call into Python! * This is the C equivalent of AFAIK, this works -- but I'm new at this. best regards, Joe