I'm trying to dump the protobuf message object using MessageToJsonString() function but encountering an exception. Sample code is as below followed by the output without try{}catch()
ResultRecord* GetSampleData()
{
auto resultRecord = std::make_unique<ResultRecord>();
....
//Filling resultRecord
....
return resultRecord.release();
}
int main(int, char**) {
//Getting RecordData through Protobuf
auto data = GetSampleData();
if(data){
std::string str;
google::protobuf::util::JsonOptions opts;
opts.add_whitespace = true;
try{
google::protobuf::util::MessageToJsonString(*(data), &str, opts);
}
catch(std::exception e)
{
std::cout<< e.what()<<std::endl;
}
std::cout<<str<<std::endl;
}
return 0;
}
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
I'm not sure what to do to debug this. Can someone point me in right direction ?
Could you try running the code under a tool like ASAN or Valgrind and see if it pinpoints the problem? The code you posted looks fine to me and I don't see any obvious problems with it. Also, does it work if you just pass a plain, empty ResultRecord to MessageToJsonString?
I tried the following as you suggested to pass empty ResultRecord
//Experimental code
ResultRecord record;
std::string str;
google::protobuf::util::MessageToJsonString(record, &str);
std::cout<<str;
Yet the result seem to be same.
anuragjain@pop-os:~/Work/build$ ./ProtobufPerf
terminate called after throwing an instance of 'std::system_error'
what(): Unknown error -1
Aborted (core dumped)
I would guess that something is wrong with the build setup then. The generated code has to be built with a protoc version matching the libprotobuf version. E.g. if you build the code with protoc 3.9.0 then make sure to link against libprotobuf 3.9.0. You also have to be careful to link against the right library--for example sometimes on Linux you might think you're linking against a locally built libprotobuf but you end up linking against an old version installed by the system in /usr. Those are just a couple of guesses as to what the problem could be. If you could get a more detailed error message from a tool like ASAN then that would help narrow down the problem as well.
@anurag-jain could you show the defination of the ResultRecord, I may test it for you.
Hi @anurag-jain ,since protobuf does not use the C++ try catch mechanism, you can try print the MessageToJsonString's return value. Maybe the return value will give you some clues.
Here are some code snippet you can refer:
if(data){
std::string str;
google::protobuf::util::Status status;
google::protobuf::util::JsonOptions opts;
opts.add_whitespace = true;
status = google::protobuf::util::MessageToJsonString(*(data), &str, opts);
std::cout<< str <<std::endl;
std::cout<<"status is:"<< status <<std::endl;
}
@anurag-jain I have had the same issue. To fix it just don't forget to link with pthreads (-lpthread option for gcc/clang).
It is because of libprotobuf is using std::call_once function, and this function actually needs in pthreads.
It is not obvious. Thus it could be worth to have it in protobuf docs.
Could you try running the code under a tool like ASAN or Valgrind and see if it pinpoints the problem? The code you posted looks fine to me and I don't see any obvious problems with it. Also, does it work if you just pass a plain, empty
ResultRecordtoMessageToJsonString?
To reproduce it you have to build example without linking with pthreads and WITHOUT sanitizers. It just because sanitizers have their own drop in replacements and interceptors for functions from pthreads.
Anyway valgrind catches nothing in this situation because it is a logic (precondition) violation inside libstdc++.
@aveselovskiy-at I had this problem too. And adding -lpthread fixed my problem. Btw, theck this https://github.com/protocolbuffers/protobuf/issues/7092 and this https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55394 .
It seems to be a bug related to GCC. And it's not fixed until Nov 3rd.
Most helpful comment
@anurag-jain I have had the same issue. To fix it just don't forget to link with pthreads (
-lpthreadoption for gcc/clang).It is because of libprotobuf is using
std::call_oncefunction, and this function actually needs in pthreads.It is not obvious. Thus it could be worth to have it in protobuf docs.