Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON Parse error when reading json object from file #3011

Closed
hari269it opened this issue Sep 9, 2021 · 6 comments
Closed

JSON Parse error when reading json object from file #3011

hari269it opened this issue Sep 9, 2021 · 6 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@hari269it
Copy link

hari269it commented Sep 9, 2021

Observing random crash when reading JSON file data to a JSON object. Here is the summary of the crash. The crash point is always consistent.

Description:

One process takes care of the following:

[Library Call] --> Returns serialised JSON key-value pair as char *, which is placed in std::string Example : std:string testString = libCall(); testString now holds a string like this {"IS_JSON_FLAGON": true}

To ensure there are no additional characters and to adhere to the JSON object compatibility, the std::string is parsed and then assigned to a JSON object

Example: nlohmann::json jWriteObj = nlohmann::json::parse(testString .c_str());

The JSON object is then written to JSON file
Example :

 mutex mLock; //global 
upDateFlagsFile()
{
    fstream fileDesc;
  
    mLock.lock();
    fileDesc.open(<filepath>, trunc mode);
    fileDesc << jWriteObj;
    fileDesc.close();
    mLock.unlock();
}

this creates/updates the file with .json extension Example: flagsFile.json with data {"IS_JSON_FLAGON":true}

In another process, the file written by the previous process is read

Modules want to know the Flag value, so calls isFlagOn("IS_JSON_FLAGON") which then opens the file and reads the data to a json object

Example: [Module reading the flag value] ---->isFlagOn("IS_JSON_FLAGON") definition for isFlagOn()

extern   mutex mLock; // using the same mutex for sync the access to file 
isFlagOn(char* flagName)
{
   istream fileDesc;
   bool flagValue = false; 
   nlohmann::json jReadObj;
try{
   mLock.lock();   
   fileDesc.open();
   fileDesc >> jReadObj; //  ---> Crash occurs randomly at this line
   flagValue = jReadObj[flagName].get<bool>();
   fileDesc.close();
   mLock.unlock();
  }
   catch(nlohmann::json::exception &e)
   {
       std:cout<< "Exception caught";
   }
   return flagValue;
}

The crash is very random on Ubuntu 20.04 and points to the line highlighted. The surprising part is the exception is not getting caught in spite of using the wildcard exception approach

Any suggestions on what needs to be corrected in this would help.

Snippet of crash:

#5 0x00007fe72ed436a9 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#6 0x000055fa7315cae9 in nlohmann::basic_json<std::map, std::vector, std::string, bool, long, unsigned long, double, std::allocator, nlohmann::adl_serializer>::operator[] (this=0x7fe67dff8840, key=0x55fa7385c64a

We are using nlohmann version 3.7.3 in our product

@nlohmann
Copy link
Owner

The stacktrace mentiones operator[], so it seems parsing is fine, but rather the access in line

flagValue = jReadObj[flagName].get<bool>();

fails. Can you replace it to

flagValue = jReadObj.at(flagName).get<bool>();

to actually throw an exception? Using operator[] on an invalid key or index will not yield an exception, but is undefined behavior.

@hari269it
Copy link
Author

Thank You for the response, I will give it a try.
The documentation mentions that the json::parse() can be used to convert C style strings to a JSON object.
Can you review the JSON methods used to write and read data to and from the file and share your suggestions?

@nlohmann
Copy link
Owner

You can parse strings like this:

json j = json::parse("[1,2,3]");

Or what do you mean?

@hari269it
Copy link
Author

As per the examples shared in ReadMe, the string can be converted to a JSON object by using the below format
auto j3 = json::parse(R"({"happy": true, "pi": 3.141})");

In the problem use case, the library call returns a char * which is then passed to json::parse before assigning to a JSON object.
The 'R' prefix is not used or cannot be used in the problem scenario.
Wanted to know if this is the right way of converting a string to a JSON object with a key value.

@nlohmann
Copy link
Owner

The R"()" notation is just a raw string literal (see https://en.cppreference.com/w/cpp/language/string_literal). This will not work with a const char* variable. You can pass these directly to the parse function.

const char* s = some_function_returning_a_c_string();
json j = json::parse(s);

@hari269it
Copy link
Author

Closed the ticket as I received the information looking for.
Thanks a lot for your response.

@nlohmann nlohmann added kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation labels Sep 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

2 participants