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 :
Which is in fact this code :
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 :
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