Permalink
Browse files

dynamic loading of mapnik datasource plugins should now work on linux…

… - workaround for lack of ability to set dlopen flags in node process to RTLD_NOW is to preload libmapnik.so symbols by having mapnik.node load itself using the RTLD_NOW flag - yes this is nuts and will hopefully be removed soon by fix upstream in node, see: https://github.com/ry/node/issues/issue/436
  • Loading branch information...
1 parent 28a1014 commit 58ece580b4710132c2e4c9dae1c6d00e3d6e08e9 Dane Springmeyer committed Nov 18, 2010
Showing with 36 additions and 0 deletions.
  1. +15 −0 mapnik/index.js
  2. +21 −0 src/_mapnik.cc
View
@@ -17,6 +17,21 @@ function warning(issue,manual_function)
console.log(msg);
}
+// hack to force libmapnik symbols to be loaded with RTLD_NOW|RTLD_GLOBAL
+// so that datasource plugins will have access to symbols since node.cc (process.dlopen)
+// uses RTLD_LAZY in its call to dlopen and has no mechanism to set the RTLD_NOW flag
+// not needed on darwin because mapnik input plugins are directly linked to libmapnik
+if (process.platform != 'darwin') {
+ var mapnik_node = path.join(__dirname,'_mapnik.node');
+ if (!path.existsSync(mapnik_node))
+ console.log(mapnik_node + ' does not exist, loading plugins will fail on linux');
+
+ var loaded = mapnik.make_mapnik_symbols_visible(mapnik_node);
+
+ if (!loaded)
+ console.log('Warning, attempt to pre-load mapnik symbols did not work, see FAQ for potential solutions');
+}
+
if (settings.paths.fonts && path.existsSync(settings.paths.fonts)) {
mapnik.register_fonts(settings.paths.fonts);
} else {
View
@@ -6,6 +6,9 @@
#include <node_buffer.h>
#include <node_version.h>
+/* dlopen(), dlsym() */
+#include <dlfcn.h>
+
// mapnik
#include <mapnik/map.hpp>
#include <mapnik/projection.hpp>
@@ -534,6 +537,23 @@ class Map: ObjectWrap
Persistent<FunctionTemplate> Map::m_template;
+static Handle<Value> make_mapnik_symbols_visible(const Arguments& args)
+{
+ if (args.Length() != 1 || !args[0]->IsString())
+ ThrowException(Exception::TypeError(
+ String::New("first argument must be a path to a directory holding _mapnik.node")));
+ String::Utf8Value filename(args[0]->ToString());
+ void *handle = dlopen(*filename, RTLD_NOW|RTLD_GLOBAL);
+ if (handle == NULL) {
+ return False();
+ }
+ else
+ {
+ dlclose(handle);
+ return True();
+ }
+}
+
static Handle<Value> register_datasources(const Arguments& args)
{
if (args.Length() != 1 || !args[0]->IsString())
@@ -707,6 +727,7 @@ extern "C" {
static void init (Handle<Object> target)
{
// module level functions
+ NODE_SET_METHOD(target, "make_mapnik_symbols_visible", make_mapnik_symbols_visible);
NODE_SET_METHOD(target, "register_datasources", register_datasources);
NODE_SET_METHOD(target, "register_fonts", register_fonts);

0 comments on commit 58ece58

Please sign in to comment.