Project

General

Profile

Multiple threads and namespaces

Added by Mike Erickson about 7 years ago

I am having a lot of trouble correctly using a custom xmp namespace from multiple threads.
Reading the documentation it is apparent that I must call XmpProperties::registerNS and XmpParser::initialize on my main thread. This I do. In my main() function I do this:

Exiv2::XmpProperties::registerNs("http://www.alienskin.com/exposure#", "alienexposure");
QMutex xmp_mutex;
Exiv2::XmpParser::initialize(XmpLockUnlock, &xmp_mutex);

where the locking function looks like:

void XmpLockUnlock(void* pData, bool fLock)
  {
QMutex* mutex_ptr = reinterpret_cast<QMutex*>(pData);
if (mutex_ptr) {
(fLock) ? mutex_ptr->lock()
: mutex_ptr->unlock();
}
}

The QMutex is taken from the stack in main(), so it should be valid for the run of the program.

There is one thread (not on the main thread ) that reads metadata. There is another thread that occasionally writes xmp metadata.
When the 2 threads both try to operate on metadata at once, there is a crash. These threads are NOT trying to write to / read from the same file.
Here is the relevant portion of the crash log on mac. I have elided some template spew for clarity. It is clearly related to a namespace operation:

0 com.alienskin.exposure7 0x0000000104dbca83 std::__1::__tree<std::__1::__value_type<std::__1::basic_string.....) + 35
1 com.alienskin.exposure7 0x0000000104db97c5 XMPMeta::DeleteNamespace(char const*) + 133
2 com.alienskin.exposure7 0x0000000104da0131 WXMPMeta_DeleteNamespace_1 + 65
3 com.alienskin.exposure7 0x0000000104d8f50c Exiv2::XmpParser::registerNs(...) + 92
4 com.alienskin.exposure7 0x0000000104d909bb Exiv2::XmpParser::encode(...) + 155
5 com.alienskin.exposure7 0x0000000104d981d6 Exiv2::XmpSidecar::writeMetadata() + 118
6 com.alienskin.exposure7 0x0000000104a9b4fe MetaDataIO::MetaDataChanged() + 2766

Could someone help me figure out what I am doing wrong?


Replies (5)

RE: Multiple threads and namespaces - Added by Robin Mills about 7 years ago

Mike

Can you have a read at this Wiki article: http://dev.exiv2.org/projects/exiv2/wiki/Thread_safety

I think that was written by Andreas. For certain, I didn't write this, and really know nothing more about this.

Robin

RE: Multiple threads and namespaces - Added by Gilles Caulier about 7 years ago

As usual, in digiKam source code, the response already exist.

We use multithreading everywhere with multicore support. digiKam use Qt/KDE Exiv2 interface libkexiv2, to wrap all Exiv2 calls to C++ exception wrapper.
The client application of libkexiv2 do not depend of Exiv2 API.

To initialize multithreading support with exiv2, this is how we do :

In main thread call this method :

https://projects.kde.org/projects/extragear/graphics/digikam/repository/revisions/master/entry/app/main/main.cpp#L92

Which is in fact this code :

https://projects.kde.org/projects/kde/kdegraphics/libs/libkexiv2/repository/revisions/master/entry/libkexiv2/kexiv2.cpp#L97

At end of application we call : https://projects.kde.org/projects/extragear/graphics/digikam/repository/revisions/master/entry/app/main/main.cpp#L238

Which is in fact this code :

https://projects.kde.org/projects/kde/kdegraphics/libs/libkexiv2/repository/revisions/master/entry/libkexiv2/kexiv2.cpp#L113

And that all... No need a mutex in your code. This work perfectly.

Gilles Caulier

RE: Multiple threads and namespaces - Added by Mike Erickson about 7 years ago

Thanks you Gilles. Looks like the main difference is you don't bother with a locking function. I will try this.

RE: Multiple threads and namespaces - Added by Mike Erickson about 7 years ago

Still crashes on mac.

RE: Multiple threads and namespaces - Added by Robin Mills about 7 years ago

Mike

Can you strip your code down to the minimum required to reproduce this and I'll have a look on one of my Macs running Mavericks.

Robin

    (1-5/5)