Loading images asynchronously

Post any defects you find in the released or beta versions of the ImageMagick software here. Include the ImageMagick version, OS, and any command-line required to reproduce the problem. Got a patch for a bug? Post it here.
Post Reply
sswiercy
Posts: 2
Joined: 2014-03-07T04:52:52-07:00
Authentication code: 6789

Loading images asynchronously

Post by sswiercy »

I'm using the MagickWand C API (6.8.7-7-Q16-x86-dll) and I encounter errors from time to time when loading multiple images concurrently. Consider the following piece of code:

Code: Select all

void loadImage(const std::string& filename) {
	
	std::ifstream file(filename,std::ifstream::binary);
	std::ostringstream blob;
	blob << file.rdbuf();

	MagickWand* wand = NewMagickWand();
	MagickReadImageBlob(wand,blob.str().data(),blob.str().size());

	ExceptionType type;
	const char* msg = MagickGetException(wand,&type);

	if (type != UndefinedException) {
		std::cout << "error: " << msg << std::endl;
	} else {
		std::cout << "successful" << std::endl;
	}

	DestroyMagickWand(wand);
}

void runner(boost::asio::io_service& service) {
	service.run();
}

int main() {

	boost::asio::io_service service;
	boost::asio::io_service::work work(service);
	service.post(boost::bind(&loadImage,std::string("test1.jpg")));
	service.post(boost::bind(&loadImage,std::string("test2.jpg")));
	boost::thread t1(boost::bind(&runner,boost::ref(service)));
	boost::thread t2(boost::bind(&runner,boost::ref(service)));
	std::cin.ignore();
	
	return EXIT_SUCCESS;
}
This code is not fully runnable but should give you an idea about how to trigger this error. It simply starts two threads which load two images concurrently. Sometimes, loading one of the images fails. The error message returned by MagickGetException then is:

no decode delegate for this image format `' @ error/blob.c/BlobToImage/358

Unfortunately, this error is hard to trigger. Often it occurs only on the first run of the application, but runs fine when executing it again. What I realized is, that this error only happens when the first images are loaded, so I could imagine that the error is due to some kind of global library initialization. Do I need to call a function for that? I tried to call MagickWandGenesis at the beginning of main, but that didn't fix it.

Thank you for any ideas about what I'm doing wrong. For now I'm using a workaround by avoiding to load images concurrently.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Loading images asynchronously

Post by magick »

Use MagickWandGenesis() before you call any other MagickWand API methods. Does that fix the problem. It should not be necessary, but perhaps that will resolve the race condition. If not, post a code segment we can download and build so we can reproduce the problem. If we can reproduce the problem, we'll have a patch available to fix the problem within a few days.
sswiercy
Posts: 2
Joined: 2014-03-07T04:52:52-07:00
Authentication code: 6789

Re: Loading images asynchronously

Post by sswiercy »

Thank you for your answer. MagickWandGenesis did not help for me. Here is a code snippet that should reproduce the error. Note that you might have to run it several times until the error occurs.

Code: Select all

#include <string>
#include <fstream>
#include <sstream>

#include <boost/thread.hpp>
#include <wand/MagickWand.h>


void load(const std::string& filename) {
   
   std::ifstream file(filename,std::ifstream::binary);
   std::ostringstream blob;
   blob << file.rdbuf();

   MagickWand* wand = NewMagickWand();
   MagickReadImageBlob(wand,blob.str().data(),blob.str().size());

   ExceptionType type;
   const char* msg = MagickGetException(wand,&type);

   if (type != UndefinedException) {
      std::cout << "error: " << msg << std::endl;
   } else {
      std::cout << "successful" << std::endl;
   }

   DestroyMagickWand(wand);
}

int main() {

	MagickWandGenesis();
	boost::thread t1(boost::bind(&load,std::string("test1.jpg")));
	boost::thread t2(boost::bind(&load,std::string("test2.jpg")));
	std::cin.ignore();
   
	return EXIT_SUCCESS;
}
Note that the Boost library is required to be installed. I think any two test images should suffice to reproduce the error.
User avatar
magick
Site Admin
Posts: 11064
Joined: 2003-05-31T11:32:55-07:00

Re: Loading images asynchronously

Post by magick »

We can reproduce the problem you posted and have a patch in ImageMagick 6.8.8-8 Beta, available in a week or two. Thanks.
Post Reply