Skip to content

Commit

Permalink
dynamic loading of mapnik datasource plugins should now work on linux…
Browse files Browse the repository at this point in the history
… - 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
Dane Springmeyer committed Nov 18, 2010
1 parent 28a1014 commit 58ece58
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
15 changes: 15 additions & 0 deletions mapnik/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
21 changes: 21 additions & 0 deletions src/_mapnik.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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);

Expand Down

1 comment on commit 58ece58

@elan
Copy link

@elan elan commented on 58ece58 Dec 31, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this was super helpful. I thought setting LD_BIND_NOW before starting node might work too, but it didn't seem to as well as this did.

Please sign in to comment.