Subject: Apache v1 in pkgsrc and dlclose()
To: None <pkgsrc-users@netbsd.org>
From: Dave Hayes <dave@jetcafe.org>
List: pkgsrc-users
Date: 06/27/2007 21:40:52
Hello. :)

This email concerns this patch to apache (version 1.3.37 or www/apache
in pkgsrc):

$NetBSD: patch-ag,v 1.8 2004/10/29 13:48:31 abs Exp $

--- src/os/unix/os.c.orig       2004-02-20 21:01:04.000000000 +0000
+++ src/os/unix/os.c
@@ -153,7 +153,12 @@ void ap_os_dso_unload(void *handle)
 #elif defined(HAVE_DYLD)
     NSUnLinkModule(handle,FALSE);
 
-#else
+/*
+ * Work around Apache dlclose() bug, where shared objects may be
+ * dlclose()d before their cleanup procedures are called.
+ * This is needed so shared modules can be used. 
+ */
+#elif 0
     dlclose(handle);
 #endif

A bit of background. 

Apache uses shared library mechanisms to manage it's external modules
(through mod_so.c). When one loads a shared apache module with the
LoadModule directive, apache does something kind of like this pseudo
code:

  module *m; 
  modhandle = dlopen(module_path, RTLD_NOW | RTLD_GLOBAL);
  m = (module *) dlsym(modhandle, modname);

Now when one does an AddModule, apache adds this to a linked list of
modules, something like:
 
  extern module *top_module;

  if (m->next == NULL) {
     m->next = top_module;
     top_module = m;
  }

This is done each time apache reads the config file, typically
once per http child. 

However, when it does this child fork, it cleans up a lot of it's
memory (ap_clear_pool()). This is supposed to do:

  dlclose(modhandle);

before running any of the LoadModule/AddModule code above. The
dlclose() appears to have the effect of resetting all the m->next
pointers back to NULL, allowing the above AddModule code to work
properly.

But wait! That patch prevents the dlclose() from happening. 

Since the handles are never closed, the "next" pointers are never set
to null. You would think that would be ok because the linked list is
already set up. Unfortunately, the compiled-in module structures (as
opposed to the dynamic shared ones) are re-initialized (including
their next pointers) and this breaks the linked list badly.

The upshot of all this is that the http daemon dies with the cryptic 
(in this case) message:

  Syntax error on line 404 of /www/apache/norm/conf/httpd.conf: 
  Invalid command 'Order', perhaps mis-spelled or defined by a module
  not included in the server configuration

This took quite a while to track down. So, before I "fix" this, I'd
like to see if anyone else has had this problem or if perhaps I am
missing something in my analysis above.  My gut feel is that the
workaround above may have more unforeseen issues, since there appears
to be no way to actually release the reference and allow the system to
perform cleanup.
------
Dave Hayes - Consultant - Altadena CA, USA - dave@jetcafe.org 
>>> The opinions expressed above are entirely my own <<<

Every stick has two ends.