[netcf-devel] [PATCH] Fix initialization of libxslt

David Lutterkort lutter at redhat.com
Fri Aug 14 01:12:38 UTC 2009


We used to initialize libxslt (and register extension modules) every time
ncf_init was called, and deregister/free libxslt globals every time
ncf_close was called. That breaks when libnetcf is used together with other
libraries that use libxslt, since they might continue using it after a call
to ncf_close.

To work around this, we now initialize and register our extension modules
only once, essentially statically, and just live with the small leak that
not unregistering and cleaning up globals causes.

Bug report and suggested fix from Daniel Veillard (<veillard at redhat.com>)
---
 configure.ac          |   17 ++++++++++++++++-
 src/drv_initscripts.c |   17 +++++++++++------
 2 files changed, 27 insertions(+), 7 deletions(-)

diff --git a/configure.ac b/configure.ac
index ff50574..b10072c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -33,7 +33,22 @@ PKG_CHECK_MODULES([LIBXSLT], [libxslt])
 
 NETCF_CHECK_READLINE
 
-NETCF_LIBDEPS=$(echo $LIBAUGEAS_LIBS $LIBXSLT_LIBS $LIBXML_LIBS)
+dnl pthread?
+have_pthread=no
+AC_CHECK_HEADER([pthread.h],
+	[AC_CHECK_LIB([pthread],[pthread_join],[
+		AC_DEFINE([HAVE_LIBPTHREAD],[],[Define if pthread (-lpthread)])
+		AC_DEFINE([HAVE_PTHREAD_H],[],[Define if <pthread.h>])
+		PTHREAD_LIBS="-lpthread $LIBS"
+        have_pthread=yes
+	])])
+
+if test $have_pthread = no; then
+    AC_MSG_ERROR(Could not find a working pthread library (see config.log for details).)
+fi
+
+
+NETCF_LIBDEPS=$(echo $LIBAUGEAS_LIBS $LIBXSLT_LIBS $LIBXML_LIBS $PTHREAD_LIBS)
 AC_SUBST([NETCF_LIBDEPS])
 
 AC_OUTPUT(Makefile                                          \
diff --git a/src/drv_initscripts.c b/src/drv_initscripts.c
index 550df65..85400cf 100644
--- a/src/drv_initscripts.c
+++ b/src/drv_initscripts.c
@@ -30,6 +30,7 @@
 #include <stdbool.h>
 #include <string.h>
 #include <unistd.h>
+#include <pthread.h>
 
 #include "safe-alloc.h"
 #include "ref.h"
@@ -91,6 +92,8 @@ static const char *const subif_paths[] = {
     "MASTER", "BRIDGE"
 };
 
+static pthread_once_t libxslt_initialized = PTHREAD_ONCE_INIT;
+
 static int is_slave(struct netcf *ncf, const char *intf) {
     for (int s = 0; s < ARRAY_CARDINALITY(subif_paths); s++) {
         int r;
@@ -244,6 +247,12 @@ static void bridge_physdevs(struct netcf *ncf) {
     return;
 }
 
+static void drv_init_once(void) {
+    // FIXME: How do we report errors ?
+    xsltInit();
+    xslt_ext_register();
+}
+
 int drv_init(struct netcf *ncf) {
     int r;
 
@@ -254,10 +263,8 @@ int drv_init(struct netcf *ncf) {
     ncf->driver->augeas_xfm_size = ARRAY_CARDINALITY(augeas_xfm);
     ncf->driver->augeas_xfm = augeas_xfm;
 
-    // FIXME: Check for errors
-    xsltInit();
-    r = xslt_ext_register();
-    ERR_THROW(r < 0, ncf, EINTERNAL, "xsltRegisterExtModule failed");
+    r = pthread_once(&libxslt_initialized, drv_init_once);
+    ERR_THROW(r != 0, ncf, EINTERNAL, "xsltRegisterExtModule failed");
     ncf->driver->get = parse_stylesheet(ncf, "initscripts-get.xsl");
     ncf->driver->put = parse_stylesheet(ncf, "initscripts-put.xsl");
     ncf->driver->rng = rng_parse(ncf, "interface.rng");
@@ -280,8 +287,6 @@ int drv_init(struct netcf *ncf) {
 void drv_close(struct netcf *ncf) {
     xsltFreeStylesheet(ncf->driver->get);
     xsltFreeStylesheet(ncf->driver->put);
-    xslt_ext_unregister();
-    xsltCleanupGlobals();
     if (ncf->driver->ioctl_fd >= 0)
         close(ncf->driver->ioctl_fd);
     aug_close(ncf->driver->augeas);
-- 
1.6.2.5



More information about the netcf-devel mailing list