Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

image_reader registration never called if static libmapnik.a is used #811

Open
artemp opened this Issue · 7 comments

2 participants

@artemp
Owner

Building mapnik with LINKING=static in order to build libmapnik.a breaks image reader initialization as the code like const bool registered = register_image_reader("png",create_png_reader); in the anonymous namespace is never called.

@springmeyer
Owner

trying to work around this I found that it is possible to repeat the declarations found in src/png_reader.cpp to get this working:

#include <iostream>
#include <mapnik/image_reader.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

/*

clang++ -o io image_io_test.cpp -I./include -Lsrc `mapnik-config --cflags --libs --ldflags` -lboost_system -L/Users/dane/projects/mapnik-packaging/osx/build-x86_64/lib/

*/

namespace mapnik
{

class png_reader : public image_reader, mapnik::noncopyable
{
private:
    std::string fileName_;
    unsigned width_;
    unsigned height_;
    int bit_depth_;
    int color_type_;
public:
    explicit png_reader(std::string const& fileName);
    ~png_reader();
    unsigned width() const;
    unsigned height() const;
    bool premultiplied_alpha() const { return false; } //http://www.libpng.org/pub/png/spec/1.1/PNG-Rationale.html
    void read(unsigned x,unsigned y,image_data_32& image);
private:
    void init();
};

image_reader* create_png_reader(std::string const& file)
{
    return new png_reader(file);
}

}


int main( int, char*[] )
{
    try
    {
        // must declare here, if global will crash with boost::lock_error
        register_image_reader("png",mapnik::create_png_reader);

        std::string  dest_fn = "./tests/data/images/dummy.png";
        std::auto_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(dest_fn,"png"));
        if (!reader.get())
        {
            throw mapnik::image_reader_exception("Failed to load: " + dest_fn);
        }
        boost::shared_ptr<mapnik::image_32> image_ptr1 = boost::make_shared<mapnik::image_32>(reader->width(),reader->height());
        reader->read(0,0,image_ptr1->data());
        std::clog << "works if you see this: " << image_ptr1->width() << "\n";

    }
    catch (std::exception const & ex)
    {
        std::clog << "C++ image i/o problem: " << ex.what() << "\n";
    }
    return 0;
}

The gocha is that if register_image_reader("png",mapnik::create_png_reader); is global like it is in png_reader.cpp then you will immediately hit this abort, which cannot be caught because it happens at startup before main():

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib          0x00007fff85d1182a __kill + 10
1   libsystem_c.dylib               0x00007fff92717a9c abort + 177
2   libc++abi.dylib                 0x00007fff8bdab7bc abort_message + 214
3   libc++abi.dylib                 0x00007fff8bda8fcf default_terminate() + 28
4   libc++abi.dylib                 0x00007fff8bda9001 safe_handler_caller(void (*)()) + 11
5   libc++abi.dylib                 0x00007fff8bda905c std::terminate() + 16
6   libc++abi.dylib                 0x00007fff8bdaa152 __cxa_throw + 114
7   io                              0x000000010a2b177e void boost::throw_exception<boost::lock_error>(boost::lock_error const&) + 414
8   io                              0x000000010a2b2440 boost::unique_lock<boost::mutex>::lock() + 192
9   io                              0x000000010a2aff98 mapnik::singleton<mapnik::factory<mapnik::image_reader, std::string, mapnik::image_reader* (*)(std::string const&), mapnik::default_factory_error>, mapnik::CreateStatic>::instance() + 56
10  io                              0x000000010a2afc9a mapnik::register_image_reader(std::string const&, mapnik::image_reader* (*)(std::string const&)) + 26
11  io                              0x000000010a2ad452 _GLOBAL__I_a + 82
12  dyld                            0x00007fff69ebbda6 ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) + 218
13  dyld                            0x00007fff69ebbaf2 ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) + 46
14  dyld                            0x00007fff69eb92e4 ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) + 260
15  dyld                            0x00007fff69eba0b7 ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) + 59
16  dyld                            0x00007fff69eaf4dd dyld::initializeMainExecutable() + 206
17  dyld                            0x00007fff69eb360b dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**) + 1852
18  dyld                            0x00007fff69ead059 _dyld_start + 49
@springmeyer
Owner

this lock error appears to be the same resulting problem as #851

@springmeyer
Owner

given this related to the singleton, also adds some more suspicious that something is not right with it as per #1459

@springmeyer
Owner

yes, same page avoids the lock error throw at startup (if register_image_reader is placed globally instead of within main):

diff --git a/include/mapnik/utils.hpp b/include/mapnik/utils.hpp
index 24a5d3d..d7b9a2d 100644
--- a/include/mapnik/utils.hpp
+++ b/include/mapnik/utils.hpp
@@ -132,7 +132,7 @@ public:
         if (! pInstance_)
         {
 #ifdef MAPNIK_THREADSAFE
-            mutex::scoped_lock lock(mutex_);
+            //mutex::scoped_lock lock(mutex_);
 #endif
             if (! pInstance_)
             {
@springmeyer
Owner

solution to #2339 might be relevant here.

@springmeyer springmeyer referenced this issue in mapnik/mapnik-support
Closed

Mapnik-iOS: Can not render png images on iPad #16

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.