summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2017-11-04 20:41:45 +0100
committerLubomir Rintel <lkundrak@v3.sk>2017-11-06 11:47:05 +0100
commit4d1f090aedf05c0e2955d431638e311d1e18a52f (patch)
treea4ba2dab0c144b48407cbe125d06c007f40a6c07
parentd529641756b5443ba86141ab13ed14952b02bdbf (diff)
downloadNetworkManager-4d1f090aedf05c0e2955d431638e311d1e18a52f.tar.gz
libnm: register empty NMClient and NetworkManager when loading libnm with GIR
Register empty "NMClient" and "NetworkManager" GIR modules as soon as libnm is loaded witch gnome-introspection. This prevents the real modules from being loaded because they would in turn load libnm-glib and abort() and crash. In particular this prevents the GNOME shell from crashing with libnm-glib abort and allows gracefully disabling the extensions which use the obsolete library. Test: $ cat test.js const NM = imports.gi.NM; print (NM.SecretAgentGetSecretsFlags.ALLOW_INTERACTION); const NMClient = imports.gi.NMClient; print (NMClient.SecretAgentGetSecretsFlags.ALLOW_INTERACTION); Before: $ gjs test.js 1 (gjs:16253): libnm-util-ERROR **: libnm symbols detected; Mixing libnm with libnm-util/libnm-glib is not supported Trace/breakpoint trap (core dumped) $ After: $ gjs test.js 1 Gjs-Message: JS WARNING: [test.js 5]: reference to undefined property "SecretAgentGetSecretsFlags" (gjs:16228): Gjs-WARNING **: JS ERROR: TypeError: NMClient.SecretAgentGetSecretsFlags is undefined @test.js:5:1 JS_EvaluateScript() failed
-rw-r--r--.gitignore3
-rw-r--r--Makefile.am18
-rw-r--r--configure.ac20
-rw-r--r--libnm/fake-typelib/NMClient.gir9
-rw-r--r--libnm/fake-typelib/NetworkManager.gir10
-rw-r--r--libnm/fake-typelib/typelibs.gresource.xml7
-rw-r--r--libnm/nm-libnm-utils.c82
7 files changed, 145 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index cd4fca45a9..c68d11f516 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,7 @@
*.gcno
*.gcda
*.la
-*.gir
+*-*.gir
*.typelib
**.stamp
.dirstamp
@@ -177,6 +177,7 @@ test-*.trs
/libnm-util/tests/test-setting-8021x
/libnm-util/tests/test-setting-dcb
+/libnm/fake-typelib/typelibs.c
/libnm/nm-settings-ifcfg-rh-docs.xml
/libnm/nm-property-docs.xml
/libnm/nm-settings-docs.xml
diff --git a/Makefile.am b/Makefile.am
index cda851a094..58be8ef91c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -858,6 +858,7 @@ nodist_libnminclude_HEADERS += \
noinst_LTLIBRARIES += libnm/libnm-utils.la
libnm_libnm_utils_la_CPPFLAGS = \
+ $(INTROSPECTION_CFLAGS) \
$(libnm_lib_cppflags)
libnm_libnm_utils_la_SOURCES = \
@@ -956,6 +957,23 @@ libnm/libnm.typelib: libnm/libnm.gir
$(INTROSPECTION_COMPILER) --includedir=$(srcdir)/libnm-core --includedir=$(builddir)/libnm-core --includedir=$(srcdir)/libnm --includedir=$(builddir)/libnm $< -o $@
INTROSPECTION_GIRS += libnm/NM-1.0.gir
+
+if WITH_FAKE_TYPELIBS
+
+libnm/fake-typelib/NetworkManager.typelib: libnm/fake-typelib/NetworkManager.gir
+ $(AM_V_GEN) $(INTROSPECTION_COMPILER) $< -o $@
+
+libnm/fake-typelib/NMClient.typelib: libnm/fake-typelib/NMClient.gir
+ $(AM_V_GEN) $(INTROSPECTION_COMPILER) $< -o $@
+
+libnm/fake-typelib/typelibs.c: libnm/fake-typelib/typelibs.gresource.xml libnm/fake-typelib/NetworkManager.typelib libnm/fake-typelib/NMClient.typelib
+ $(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $< --target=$@ --sourcedir=$(srcdir)/libnm/fake-typelib --generate-source --manual-register --internal
+
+libnm_libnm_utils_la_SOURCES += \
+ libnm/fake-typelib/typelibs.c
+
+endif
+
endif
if HAVE_INTROSPECTION
diff --git a/configure.ac b/configure.ac
index 061c7738e3..ad188a7763 100644
--- a/configure.ac
+++ b/configure.ac
@@ -322,9 +322,12 @@ GLIB_CFLAGS="$GLIB_CFLAGS -DGLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_32 -DGLIB_V
AC_SUBST(GLIB_CFLAGS)
AC_SUBST(GLIB_LIBS)
+GOBJECT_INTROSPECTION_CHECK([0.9.6])
+
AC_ARG_WITH(libnm-glib,
AS_HELP_STRING([--without-libnm-glib],
- [don't build legacy libraries]))
+ [don"'"t build legacy libraries]))
+fake_typelibs=no
if test "$with_libnm_glib" != "no"; then
PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.1 dbus-glib-1 >= 0.94, :,
[AC_MSG_FAILURE([$DBUS_PKG_ERRORS
@@ -333,13 +336,24 @@ Configure with --without-libnm-glib if you do not need the legacy libraries])
])
with_libnm_glib=yes
+
+ if test "${found_introspection}" = "yes"; then
+ AC_PATH_PROG(GLIB_COMPILE_RESOURCES, glib-compile-resources)
+ if ! test x"$GLIB_COMPILE_RESOURCES" = x""; then
+ fake_typelibs=yes
+ fi
+ fi
fi
AM_CONDITIONAL(WITH_LEGACY_LIBRARIES, test "$with_libnm_glib" != "no")
+if test "$fake_typelibs" = "yes"; then
+ AC_DEFINE(WITH_FAKE_TYPELIBS, 1, [Define for libnm to prevent GIR from loading libnm-glib])
+else
+ AC_DEFINE(WITH_FAKE_TYPELIBS, 0, [Define for libnm to prevent GIR from loading libnm-glib])
+fi
+AM_CONDITIONAL(WITH_FAKE_TYPELIBS, test "${fake_typelibs}" = "yes")
PKG_CHECK_MODULES([LIBUDEV], [libudev >= 175])
-GOBJECT_INTROSPECTION_CHECK([0.9.6])
-
# Qt4
PKG_CHECK_MODULES(QT, [QtCore >= 4 QtDBus QtNetwork], [have_qt=yes],[have_qt=no])
AC_ARG_ENABLE(qt,
diff --git a/libnm/fake-typelib/NMClient.gir b/libnm/fake-typelib/NMClient.gir
new file mode 100644
index 0000000000..3002f8d630
--- /dev/null
+++ b/libnm/fake-typelib/NMClient.gir
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!-- A lame duck typelib which prevents GIR from loading the
+ real one (which would crash due to conflict with libnm) -->
+<repository version="1.2"
+ xmlns="http://www.gtk.org/introspection/core/1.0"
+ xmlns:c="http://www.gtk.org/introspection/c/1.0"
+ xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+ <namespace name="NMClient" version="0.0" />
+</repository>
diff --git a/libnm/fake-typelib/NetworkManager.gir b/libnm/fake-typelib/NetworkManager.gir
new file mode 100644
index 0000000000..d15d29afc7
--- /dev/null
+++ b/libnm/fake-typelib/NetworkManager.gir
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!-- A lame duck typelib which prevents GIR from loading the
+ real one (which would crash due to conflict with libnm) -->
+<repository version="1.2"
+ xmlns="http://www.gtk.org/introspection/core/1.0"
+ xmlns:c="http://www.gtk.org/introspection/c/1.0"
+ xmlns:glib="http://www.gtk.org/introspection/glib/1.0">
+ <namespace name="NetworkManager" version="0.0">
+ </namespace>
+</repository>
diff --git a/libnm/fake-typelib/typelibs.gresource.xml b/libnm/fake-typelib/typelibs.gresource.xml
new file mode 100644
index 0000000000..9a71d97544
--- /dev/null
+++ b/libnm/fake-typelib/typelibs.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/freedesktop/libnm/fake-typelib">
+ <file>NetworkManager.typelib</file>
+ <file>NMClient.typelib</file>
+ </gresource>
+</gresources>
diff --git a/libnm/nm-libnm-utils.c b/libnm/nm-libnm-utils.c
index fbbfe2c552..a01228d5bb 100644
--- a/libnm/nm-libnm-utils.c
+++ b/libnm/nm-libnm-utils.c
@@ -23,6 +23,8 @@
#include "nm-libnm-utils.h"
+#include <girepository.h>
+
/*****************************************************************************/
char *
@@ -160,3 +162,83 @@ next:
nm_assert (g_utf8_validate (desc_full, -1, NULL));
return desc_full;
}
+
+#if WITH_FAKE_TYPELIBS
+
+/*
+ * Here we register empty "NMClient" and "NetworkManager" GIR modules as soon
+ * as we are loaded (if gnome-introspection is being used). This prevents the
+ * real modules from being loaded because they would in turn load libnm-glib
+ * and abort() and crash.
+ *
+ * For the high level languages that utilize GIR the crash is highly inconvenient
+ * while the inability to resolve any methods and attributes is potentially
+ * recoverable.
+ */
+
+GResource *typelibs_get_resource (void);
+void typelibs_register_resource (void);
+
+static void __attribute__((constructor))
+_nm_libnm_utils_init (void)
+{
+ GITypelib *typelib;
+ GBytes *data;
+ const char *namespace;
+ GModule *self;
+ GITypelib *(*_g_typelib_new_from_const_memory) (const guint8 *memory,
+ gsize len,
+ GError **error) = NULL;
+ const char *(*_g_irepository_load_typelib) (GIRepository *repository,
+ GITypelib *typelib,
+ GIRepositoryLoadFlags flags,
+ GError **error) = NULL;
+ const char *names[] = { "/org/freedesktop/libnm/fake-typelib/NetworkManager.typelib",
+ "/org/freedesktop/libnm/fake-typelib/NMClient.typelib" };
+ int i;
+
+ self = g_module_open (NULL, 0);
+ if (!self)
+ return;
+ g_module_symbol (self, "g_typelib_new_from_const_memory",
+ (gpointer *) &_g_typelib_new_from_const_memory);
+ if (_g_typelib_new_from_const_memory) {
+ g_module_symbol (self, "g_irepository_load_typelib",
+ (gpointer *) &_g_irepository_load_typelib);
+ }
+ g_module_close (self);
+
+ if (!_g_typelib_new_from_const_memory || !_g_irepository_load_typelib)
+ return;
+
+ typelibs_register_resource ();
+
+ for (i = 0; i < 2; i++) {
+ gs_free_error GError *error = NULL;
+
+ data = g_resource_lookup_data (typelibs_get_resource (),
+ names[i],
+ G_RESOURCE_LOOKUP_FLAGS_NONE,
+ &error);
+ if (!data) {
+ g_warning ("Fake typelib %s could not be loaded: %s", names[i], error->message);
+ return;
+ }
+
+ typelib = _g_typelib_new_from_const_memory (g_bytes_get_data (data, NULL),
+ g_bytes_get_size (data),
+ &error);
+ if (!typelib) {
+ g_warning ("Could not create fake typelib instance %s: %s", names[i], error->message);
+ return;
+ }
+
+ namespace = _g_irepository_load_typelib (NULL, typelib, 0, &error);
+ if (!namespace) {
+ g_warning ("Could not load fake typelib %s: %s", names[i], error->message);
+ return;
+ }
+ }
+}
+
+#endif /* WITH_FAKE_TYPELIBS */