Page 1 of 1

Segmentation fault at dlclose

Posted: 2013-03-07T01:28:10-07:00
by Alxv
I'm loading libmagickwand dynamicly with dlopen.
But my program segfault at dlclose.
Here it is program source code:

Code: Select all

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <dlfcn.h>

typedef enum
{
  MagickFalse = 0,
  MagickTrue = 1
} MagickBooleanType;

typedef enum
{
  CharPixel = 1
} StorageType;

typedef enum
{
  SincFilter = 15
} FilterTypes;

typedef enum
{
  RedChannel   = 0x0001,
  GreenChannel = 0x0002,
  BlueChannel  = 0x0004,
  AlphaChannel = 0x0008,
} ChannelType;

typedef void MagickWand;

void (*MagickWandGenesis)(void);
void (*MagickWandTerminus)(void);
MagickWand *(*NewMagickWand)(void);
MagickWand *(*DestroyMagickWand)(MagickWand *wand);

MagickBooleanType (*MagickReadImage)(MagickWand *wand, const char *filename);
MagickBooleanType (*MagickSetImageFormat)(MagickWand *wand, const char *format);
MagickBooleanType (*MagickSetImageChannelDepth)
    (MagickWand *wand, const ChannelType channel, const unsigned long depth);
unsigned char *(*MagickGetImageBlob)(MagickWand *wand, size_t *length);
unsigned long (*MagickGetImageWidth)(MagickWand *wand);
unsigned long (*MagickGetImageHeight)(MagickWand *wand);
void *(*MagickRelinquishMemory)(void *resource);

void *libmagickwand;

#define get_func(func) (func = dlsym(libmagickwand, #func))

void libmagickwand_init(void)
{
    if (libmagickwand == NULL)
    {
        libmagickwand = dlopen("libMagickWand.so.3", RTLD_LAZY);
        if (libmagickwand == NULL)
        {
            fputs(dlerror(), stderr);
            return;
        }
        if
        (
            get_func(MagickWandGenesis)          == NULL ||
            get_func(MagickWandTerminus)         == NULL ||
            get_func(NewMagickWand)              == NULL ||
            get_func(DestroyMagickWand)          == NULL ||
            get_func(MagickReadImage)            == NULL ||
            get_func(MagickSetImageFormat)       == NULL ||
            get_func(MagickSetImageChannelDepth) == NULL ||
            get_func(MagickGetImageBlob)         == NULL ||
            get_func(MagickGetImageWidth)        == NULL ||
            get_func(MagickGetImageHeight)       == NULL ||
            get_func(MagickRelinquishMemory)     == NULL
        )
        {
            fputs("Some function missing in \"libMagickWand.so.3\"", stderr);
            dlclose(libmagickwand);
            libmagickwand = NULL;
            return;
        }
        MagickWandGenesis();
    }
}

void libmagickwand_free()
{
    if (libmagickwand != NULL)
    {
        MagickWandTerminus();
        dlclose(libmagickwand);
        libmagickwand = NULL;
    }
}

typedef struct
{
    uint32_t width, height, *rgba;
} image;

int load_image(char *file, image *img)
{
    if (libmagickwand == NULL)
        return 0;

    MagickWand *mw = NewMagickWand();
    if (mw == NULL)
        return 1;

    int result = 0;
    unsigned char *blob;
    size_t blob_len;
    if
    (
        MagickReadImage(mw, file)        &&
        MagickSetImageFormat(mw, "RGBA") &&
        MagickSetImageChannelDepth
            (mw, RedChannel | GreenChannel | BlueChannel | AlphaChannel, 8) &&
        (blob = MagickGetImageBlob(mw, &blob_len))
    )
    {
        img->width = MagickGetImageWidth(mw);
        img->height = MagickGetImageHeight(mw);
        img->rgba = malloc(blob_len);
        memcpy(img->rgba, blob, blob_len);
        MagickRelinquishMemory(blob);
        result = 1;
    }

    DestroyMagickWand(mw);

    return result;
    
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        puts("Usage: image2rgba FILE");
        return EXIT_SUCCESS;
    }

    libmagickwand_init();

    image img;
    if (load_image(argv[1], &img))
    {
        puts("Image loaded. We can use it, for example, as OpenGL's texture.");
        free(img.rgba);
    }
    else
    {
        puts("Failed to load image.");
    }

    libmagickwand_free();

    return EXIT_SUCCESS;
} 
To compile run gcc image2rgba.c -g3 -O0 -ldl -o image2rgba
And this is gdb backtrace:

Code: Select all

#0  0xb76f84e0 in ?? () from /usr/lib/libgomp.so.1
#1  0xb76f869b in ?? () from /usr/lib/libgomp.so.1
#2  0xb76f6d40 in ?? () from /usr/lib/libgomp.so.1
#3  0xb7fcc7b0 in start_thread (arg=0xb6134b70) at pthread_create.c:300
#4  0xb7f2d1de in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:130
Segfault disapper if I compile with -fopenmp option.
Is this problem has any other solution?

Re: Segmentation fault at dlclose

Posted: 2013-03-07T04:55:39-07:00
by magick
OpenMP threads the ImageMagick algorithms and provides a performance boost on multi-core processors. You can remove the OpenMP dependence on libgomp by adding --disable-openmp on the configure script command line when building ImageMagick:
  • cd ImageMagick-6.8.3-7
    ./configure --disable-openm
    make
    make install