Json Spirit not thread safe on Ubuntu

A few days ago I noticed a lot of fast crashes of my program after adding multithreading to it. GDB showed the segfault in json_spirit::read(). So I wondered if that is a thread safety issue. I could not find any information about whether the json spirit package for ubuntu is thread safe or not. A simple test reproduces this behaviour:

#include <json_spirit.h>
#include <thread>
#include <vector>
#include <mutex>
 
void test()
{
	json_spirit::mValue v;
	for(int i = 0; i < 1000; ++i)
		json_spirit::read("{}", v);	
}
int main()
{
	std::vector<std::thread> threads;
	for(int i = 0; i < 8; ++i)
		threads.emplace_back(test);
	for (auto& th : threads)
		th.join();
}
clang++ test.cxx -pthread -ljson_spirit -std=c++11 -O0 -g3

The test program crashes immediately at least on my system (Ubuntu 14.04, libjson-spirit-dev 4.05-1.1). The Backtrace looks like this:

#0  0x00007ffff0000960 in ?? ()
#1  0x000000000042e0de in __gnu_cxx::__normal_iterator<char const*, std::string> json_spirit::read_range_or_throw<__gnu_cxx::__normal_iterator<char const*, std::string>, json_spirit::Value_impl<json_spirit::Config_map<std::string> > >(__gnu_cxx::__normal_iterator<char const*, std::string>, __gnu_cxx::__normal_iterator<char const*, std::string>, json_spirit::Value_impl<json_spirit::Config_map<std::string> >&) ()
#2  0x000000000042e1bc in bool json_spirit::read_range<__gnu_cxx::__normal_iterator<char const*, std::string>, json_spirit::Value_impl<json_spirit::Config_map<std::string> > >(__gnu_cxx::__normal_iterator<char const*, std::string>&, __gnu_cxx::__normal_iterator<char const*, std::string>, json_spirit::Value_impl<json_spirit::Config_map<std::string> >&) ()
#3  0x00000000004080fd in json_spirit::read(std::string const&, json_spirit::Value_impl<json_spirit::Config_map<std::string> >&) ()
#4  0x00000000004028fb in test () at test.cxx:10
#5  0x0000000000404f3f in std::_Bind_simple<void (*())()>::_M_invoke<>(std::_Index_tuple<>) (this=0x6f3060) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1731
#6  0x0000000000404f15 in std::_Bind_simple<void (*())()>::operator()() (this=0x6f3060) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:1720
#7  0x0000000000404eec in std::thread::_Impl<std::_Bind_simple<void (*())()> >::_M_run() (this=0x6f3048) at /usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/thread:115
#8  0x00007ffff7b87bf0 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x00007ffff73a4182 in start_thread (arg=0x7ffff6fd5700) at pthread_create.c:312
#10 0x00007ffff70d130d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

Adding a mutexed thread safe wrapper function which calls json_spirit::read() fixed the problem:

#include <json_spirit.h>
#include <thread>
#include <vector>
#include <mutex>
 
bool js_read(const std::string& js, json_spirit::mValue& v)
{
	static std::mutex mtx;
	std::lock_guard<std::mutex> lock(mtx);
	return json_spirit::read(js, v);
}
void test()
{
	json_spirit::mValue v;
	for(int i = 0; i < 1000; ++i)
		js_read("{}", v);	
}
int main()
{
	std::vector<std::thread> threads;
	for(int i = 0; i < 8; ++i)
		threads.emplace_back(test);
	for (auto& th : threads)
		th.join();
}

Note that the initialization of the static local mutex is only thread safe since C++11. Alternativly you have to use a global mutex.