From 58ece580b4710132c2e4c9dae1c6d00e3d6e08e9 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 18 Nov 2010 13:36:51 -0800 Subject: [PATCH] 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 --- mapnik/index.js | 15 +++++++++++++++ src/_mapnik.cc | 21 +++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/mapnik/index.js b/mapnik/index.js index 912f5d18a7..25cce90d88 100644 --- a/mapnik/index.js +++ b/mapnik/index.js @@ -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 { diff --git a/src/_mapnik.cc b/src/_mapnik.cc index b282e6a03e..391b3751bc 100644 --- a/src/_mapnik.cc +++ b/src/_mapnik.cc @@ -6,6 +6,9 @@ #include #include +/* dlopen(), dlsym() */ +#include + // mapnik #include #include @@ -534,6 +537,23 @@ class Map: ObjectWrap Persistent Map::m_template; +static Handle 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 register_datasources(const Arguments& args) { if (args.Length() != 1 || !args[0]->IsString()) @@ -707,6 +727,7 @@ extern "C" { static void init (Handle 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);