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.

2 thoughts on “Json Spirit not thread safe on Ubuntu

  1. The json spirit packaged with ubuntu is compiled with thread safety disabled.
    You can download the source version and recompile it enabling this define:

    json_spirit/json_spirit_reader_template.h:#define BOOST_SPIRIT_THREADSAFE // uncomment for multithreaded use, requires linking to boost.thread

Leave a Reply

Your email address will not be published.

Time limit is exhausted. Please reload CAPTCHA.