C++11 function static variable initialization weirdness - multithreading
I have plain simple function that maps some HTTP status codes to strings:
const std::string & status_name(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
One day, on our test servers, a crash has occurred. Analysing core dump is seems that std::out_of_range exception was thrown in status_table.at(0);. Another weird thing is that status code in question was 200. Program that crashed abuses multiple threads, so my stomach feel tells me that this issue is thread-related.
I'm really puzzled about how it's even possible. It's C++11 and this version of standard provides guarantees regarding thread-safety of static variable initialization. The compiler is clang-3.3, architecture is x64 and CPU is Intel(R) Xeon(R) CPU E5506.
The only two things come to mind:
there's some bug in the code I miss to see;
this weirdness is related to CPU cache incoherency: thread that caused crash saw guard variable as indicating 'initialized' state of
status_table but object itself was seen empty.
Update on the issue:
After making a small test case I was able to easily reproduce the problem:
#include <thread>
#include <atomic>
#include <string>
#include <unordered_map>
#include <vector>
#include <memory>
#include <iostream>
#include <unistd.h>
const std::string & status_name1(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
const std::string & status_name2(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
const std::string & status_name3(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
const std::string & status_name4(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
const std::string & status_name5(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
const std::string & status_name6(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
const std::string & status_name7(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
const std::string & status_name8(int code)
{
static std::unordered_map<int, std::string> status_table {
{ 0, "UNKNOWN" },
{ 100, "Continue" },
{ 101, "Switching Protocols" },
{ 200, "OK" },
{ 201, "Created" },
{ 202, "Accepted" },
{ 203, "Non-Authoritative Information" },
{ 204, "No Content" },
{ 205, "Reset Content" },
{ 206, "Partial Content" },
{ 300, "Multiple Choices" },
{ 301, "Moved Permanently" },
{ 302, "Found" },
{ 303, "See Other" },
{ 304, "Not Modified" },
{ 305, "Use Proxy" },
{ 307, "Temporary Redirect" },
{ 400, "Bad Request" },
{ 401, "Unauthorized" },
{ 402, "Payment Required" },
{ 403, "Forbidden" },
{ 404, "Not Found" },
{ 405, "Method Not Allowed" },
{ 406, "Not Acceptable" },
{ 407, "Proxy Authentication Required" },
{ 408, "Request Timeout" },
{ 409, "Conflict" },
{ 410, "Gone" },
{ 411, "Length Required" },
{ 412, "Precondition Failed" },
{ 413, "Request Entity Too Large" },
{ 414, "Request-URI Too Long" },
{ 415, "Unsupported Media Type" },
{ 416, "Requested Range Not Satisfiable" },
{ 417, "Expectation Failed" },
{ 499, "Rotten session" },
{ 500, "Internal Server Error" },
{ 501, "Not Implemented" },
{ 502, "Bad Gateway" },
{ 503, "Service Unavailable" },
{ 504, "Gateway Timeout" },
{ 505, "HTTP Version Not Supported" },
};
auto it = status_table.find(code);
if (it != status_table.end())
return it->second;
return status_table.at(0);
}
int main(int argc, char ** argv)
{
std::vector<std::thread> thread_pool;
auto guard_variable = std::make_shared<std::atomic<int>>(0);
for (int i = 0; i < 8; ++i) {
thread_pool.push_back(std::thread([guard_variable] {
while (!guard_variable->load(std::memory_order_relaxed)) {
/// Noop.
}
int i = 0;
i += status_name1(200).length();
i += status_name2(200).length();
i += status_name3(200).length();
i += status_name4(200).length();
i += status_name5(200).length();
i += status_name6(200).length();
i += status_name7(200).length();
i += status_name8(200).length();
std::cout << i << std::endl;
}));
}
usleep(50000);
guard_variable->store(1, std::memory_order_relaxed);
for (auto && thread : thread_pool) {
thread.join();
}
return 0;
}
This code works as expected everywhere else other than on that test machine. No matter what version of clang I use (3.3, 3.6) this test program crashes due to exception immediately, at different times in different status_name* function.
What can possibly cause this behaviour? Is CPU cache inconsistency or is it bug in libc++?
Clang supports "magic statics" (N2660 Dynamic initialization and destruction with concurrency) since 2.9 per http://clang.llvm.org/cxx_status.html.
Rather than a bug in the compiler or your immediate code, it is more likely that a bug elsewhere in your code is corrupting program state, causing status_table to appear initialized but empty.
Related
How to Map the nested array using map function?
I/P: [ { "keyword": "outdoor cushion", "bidInfo": [ { "matchType": "EXACT", "theme": "CONVERSION_OPPORTUNITIES", "rank": 1, "bid": 160, "suggestedBid": { "rangeStart": 90, "rangeMedian": 160, "rangeEnd": 188 } }, { "matchType": "PHRASE", "theme": "CONVERSION_OPPORTUNITIES", "rank": 1, "bid": 104, "suggestedBid": { "rangeStart": 83, "rangeMedian": 104, "rangeEnd": 177 } }, { "matchType": "BROAD", "theme": "CONVERSION_OPPORTUNITIES", "rank": 1, "bid": 106, "suggestedBid": { "rangeStart": 87, "rangeMedian": 106, "rangeEnd": 139 } } ], "translation": "アウトドアクッション", "userSelectedKeyword": false, "searchTermImpressionRank": 18, "searchTermImpressionShare": 0.7346906874047442, "recId": "e4918800-d0bf-4f20-8776-68574e4c8339" }, { "keyword": "cushion", "bidInfo": [ { "matchType": "EXACT", "theme": "CONVERSION_OPPORTUNITIES", "rank": 2, "bid": 140, "suggestedBid": { "rangeStart": 140, "rangeMedian": 140, "rangeEnd": 140 } }, { "matchType": "BROAD", "theme": "CONVERSION_OPPORTUNITIES", "rank": 2, "bid": 111, "suggestedBid": { "rangeStart": 79, "rangeMedian": 111, "rangeEnd": 155 } }, { "matchType": "PHRASE", "theme": "CONVERSION_OPPORTUNITIES", "rank": 2, "bid": 107, "suggestedBid": { "rangeStart": 76, "rangeMedian": 107, "rangeEnd": 149 } } ], "translation": "クッション", "userSelectedKeyword": false, "searchTermImpressionRank": 60, "searchTermImpressionShare": 0.04246088993932697, "recId": "50a5705a-d79a-4f74-82bd-2836096b36fd" } ] trying: const suggestionSp: { Rank: string; searchTerm: string; matchType: string; low: string; suggestedBid: string; high: string; translation: string; }[] = []; if (suggestions.keywordTargetList.length > 0) { await suggestions.keywordTargetList.map((item: { rank: string; keyword: string; matchType: string; suggestedBid: any; bid: any; bidInfo: any[]; translation: any; }) => { suggestionSp.push({Rank: item.bidInfo.rank, searchTerm: item.keyword, matchType: item.bidInfo.matchType, low: item.bidInfo.suggestedBid.rangeStart, suggestedBid: item.bidInfo.suggestedBid.rangeMedian, high: item.bidInfo.suggestedBid.rangeEnd, translation: item.translation }); }); } Expected O/P: [{ "keyword": "outdoor cushion", "matchType": "EXACT", "rank": 1, "rangeStart": 92, "rangeMedian": 163, "rangeEnd": 191, "translation": "アウトドアクッション" }, { "keyword": "outdoor cushion", "matchType": "PHRASE", "rank": 1, "rangeStart": 83, "rangeMedian": 103, "rangeEnd": 176, "translation": "アウトドアクッション" }, { "matchType": "BROAD", "rank": 1, "rangeStart": 88, "rangeMedian": 107, "rangeEnd": 141, "translation": "アウトドアクッション" } ]
You can use the array's reduce method: const output = input.reduce((result, current) => result.concat( current.bidInfo.map(bidInfo => ({ "keyword": current.keyword, "matchType": bidInfo.matchType, "rank": bidInfo.rank, "rangeStart": bidInfo.suggestedBid.rangeStart, "rangeMedian": bidInfo.suggestedBid.rangeMedian, "rangeEnd": bidInfo.suggestedBid.rangeEnd, "translation": current.translation }) )), []); Used Reduce syntax: reduce((accumulator, currentValue) => { /* … */ } , initialValue)
Updating dictionary in Python
I'm working on a project where I will retrieve data from various files and this data will then be written down in a file in geojson format. Below you see a simplified example of some of the code and output: Code: def get_data(data): features = { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ data["lat"], data["long"], ], }, "properties": { "obsid": data["file_name"], "name": data["guid_id"], "h_gs": data["z"], }, } ], } for id, top, bot, code in zip( data["id"], data["top"], data["bot"], data["code"], ): info = { id: { "top": top, "bot": bot, "code": code, }, } features["features"].append(info) return features def main(data): data = get_data(data) to_json = json.dumps(data, indent=4) print(to_json) if __name__ == "__main__": # example data data = { "lat": 40.730610, "long": -73.935242, "z": 28.37, "file_name": "tmrx.txt", "guid_id": "d4d5b10a-c5fc-450a-9b3b-f309e7cb9613", "id": ["id_0", "id_1", "id_2", "id_3", "id_4"], "top": [100, 200, 300, 400, 500], "bot": [90, 190, 290, 390, 490], "code": ["a", "b", "c", "d", "e"], } main(data) Output: { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ 40.73061, -73.935242 ] }, "properties": { "obsid": "tmrx.txt", "name": "d4d5b10a-c5fc-450a-9b3b-f309e7cb9613", "h_gs": 28.37 } }, { "id_0": { "top": 100, "bot": 90, "code": "a" } }, { "id_1": { "top": 200, "bot": 190, "code": "b" } }, { "id_2": { "top": 300, "bot": 290, "code": "c" } }, { "id_3": { "top": 400, "bot": 390, "code": "d" } }, { "id_4": { "top": 500, "bot": 490, "code": "e" } } ] } This works fine but I wish I could get the output to look a little different. Desired output: { "type": "FeatureCollection", "features": [ { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ 40.73061, -73.935242 ] }, "properties": { "obsid": "tmrx.txt", "name": "d4d5b10a-c5fc-450a-9b3b-f309e7cb9613", "h_gs": 28.37 } "id_0": { "top": 100, "bot": 90, "code": "a" } "id_1": { "top": 200, "bot": 190, "code": "b" } "id_2": { "top": 300, "bot": 290, "code": "c" } "id_3": { "top": 400, "bot": 390, "code": "d" } "id_4": { "top": 500, "bot": 490, "code": "e" } } ] } There, the 'unnecessary' brackets are removed. Does anyone here on the forum know how i could achieve this result in the above code? Best Regards, Mikael See the code sample above.
Change below Line in your code features["features"].append(info) To this features["features"][0] |= info
Instead of features["features"].append(info) use: features["features"][0].update(info)
Getting error "There was a problem with the requested skill's response" while developing Alexa Skill through Alexa Developers Console?
When testing out my skill using the Test Simulator for Alexa I am getting the following error: "There was a problem with the requested skill's response" I tried looking at solutions, but I could not find anything. Below is my JSON Input 1 and I am not getting anything in JSON output. Please help me here? { "version": "1.0", "session": { "new": true, "sessionId": "amzn1.echo-api.session.8df6ac89-2811-43cf-8578-e9edc30fa091", "application": { "applicationId": "amzn1.ask.skill.b1f0f00c-d3a9-43b9-82fe-92f066c58880" }, "user": { "userId": "amzn1.ask.account.AHNEWQLTUHO42PDYBLNORMFZURAPP5WSA52C6HPP4GEUM3MPBRYTY6WKULN3BNXIKPEOLUDQMX7EOLCG3E7LCD3YPJ4QL5JZ2N2UTX4UUFIWFY5PVGNSWC4JVO2EVFV5TDJD6HIPHU5O4KTSQW7XWBTUCSZ4JFPMFBPKEQ5IFLBZMXJI2XSRSMXKJV3PVJRSR5OT32LGO74AP2A" } }, "context": { "System": { "application": { "applicationId": "amzn1.ask.skill.b1f0f00c-d3a9-43b9-82fe-92f066c58880" }, "user": { "userId": "amzn1.ask.account.AHNEWQLTUHO42PDYBLNORMFZURAPP5WSA52C6HPP4GEUM3MPBRYTY6WKULN3BNXIKPEOLUDQMX7EOLCG3E7LCD3YPJ4QL5JZ2N2UTX4UUFIWFY5PVGNSWC4JVO2EVFV5TDJD6HIPHU5O4KTSQW7XWBTUCSZ4JFPMFBPKEQ5IFLBZMXJI2XSRSMXKJV3PVJRSR5OT32LGO74AP2A" }, "device": { "deviceId": "amzn1.ask.device.AHUW3YVJLFTNIZQ7UUMLHULHQWHKPMW2UICHN4DZRBGBSYZJ3LMSUZLC4LP7Q5F4M7IXQOCAJ4KFNFB7GVAIRLIOHK7YN62XTX6LKRODFUKR2LP4RSGJUQCJGHXP7KIEFULCF6GVQD77DVPOC6OILLKGPEKADVW253ZEOJX4FGLG2SVWZMFHW", "supportedInterfaces": {} }, "apiEndpoint": "https://api.eu.amazonalexa.com", "apiAccessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJhdWQiOiJodHRwczovL2FwaS5hbWF6b25hbGV4YS5jb20iLCJpc3MiOiJBbGV4YVNraWxsS2l0Iiwic3ViIjoiYW16bjEuYXNrLnNraWxsLmIxZjBmMDBjLWQzYTktNDNiOS04MmZlLTkyZjA2NmM1ODg4MCIsImV4cCI6MTU4NTQ5NTU5NSwiaWF0IjoxNTg1NDk1Mjk1LCJuYmYiOjE1ODU0OTUyOTUsInByaXZhdGVDbGFpbXMiOnsiY29udGV4dCI6IkFBQUFBQUFBQVFDemhJWnNHUzR1L1cwK3VETTVuTkNjS2dFQUFBQUFBQUFZbjJTTllsbEhmUlVkbkFLU3E4Y0R3dXlNR2krUlUrWE90MVFuWXpkSERJUlpwUkhxdEoxcUZvMGRsM2YrRHFRSHJNeFFLaTlLR3FLa1RJQjlPOGJpUzcxZi9vMWJ6d1cvWlplcCtLTDlhem9yRUxYNjFXN2VBM3JnTy9PZkc0a1M4c1h5M2dmYTdEakxaUkRmUW9PWGZhZVJHa3p2Y1phUWQ4cmw4bDRWRlVsUnNLeEZadU9icmR3MTcvUkkxVHlWNERibFFhSHZjRXRtNUZJcnI4dmJ2bENyM3ZCWnJEVVFCSmxEN0ZrMG1lLzEwUHh2bnM1V05tcUl4ODN3WUFiUmdIUHEramhVZUpjM1lFcEpUYjcwZEllaHVoNUN4SDg3ZWZ5ckJPRDZFSnUwU1RCbmRQZGhnaXZnS3FNZUdVYkNWQmtzYmhVR1BIQy9HdjQxVmNlcDB2OXkrVk1iZFNROXFXbWV0aS9USm5hUFZWeVpyRFdLd0JDTGZ1RVoyWlloc2JzOGQxNTNPQlg2IiwiY29uc2VudFRva2VuIjpudWxsLCJkZXZpY2VJZCI6ImFtem4xLmFzay5kZXZpY2UuQUhVVzNZVkpMRlROSVpRN1VVTUxIVUxIUVdIS1BNVzJVSUNITjREWlJCR0JTWVpKM0xNU1VaTEM0TFA3UTVGNE03SVhRT0NBSjRLRk5GQjdHVkFJUkxJT0hLN1lONjJYVFg2TEtST0RGVUtSMkxQNFJTR0pVUUNKR0hYUDdLSUVGVUxDRjZHVlFENzdEVlBPQzZPSUxMS0dQRUtBRFZXMjUzWkVPSlg0RkdMRzJTVldaTUZIVyIsInVzZXJJZCI6ImFtem4xLmFzay5hY2NvdW50LkFITkVXUUxUVUhPNDJQRFlCTE5PUk1GWlVSQVBQNVdTQTUyQzZIUFA0R0VVTTNNUEJSWVRZNldLVUxOM0JOWElLUEVPTFVEUU1YN0VPTENHM0U3TENEM1lQSjRRTDVKWjJOMlVUWDRVVUZJV0ZZNVBWR05TV0M0SlZPMkVWRlY1VERKRDZISVBIVTVPNEtUU1FXN1hXQlRVQ1NaNEpGUE1GQlBLRVE1SUZMQlpNWEpJMlhTUlNNWEtKVjNQVkpSU1I1T1QzMkxHTzc0QVAyQSJ9fQ.L0hwnl1wAddgWkZBxbu9Q4nRHlzwWglcSiqzf4Z_Nzg8C4XzsP9-5x_wccMpDWRPQxE5s0YOf6UfkCooakR36lVkm6Z7PhVqJShNrF6YooC29vjJ50C1-_wg27AwcDWXBG4c_tjDTFcrAuwkNOo3pBUjA9xE00a3q6Ecs-UtD-stQXoLv4J0f8bpe7AEpfc1pzaqhBXkybYYA91IFLVX67Gvxqiag2CwjdT6BO0uayQqZpXZd5F4IRfYuLmsqK0aFIJv5g0h_kfwPusowLkGneegE2uTLE5SwZpZkWg9-aI-6HvdvRe1DvZbgnJKjw2SBRNGdKT-UOkJZTndI3mgag" }, "Viewport": { "experiences": [ { "arcMinuteWidth": 246, "arcMinuteHeight": 144, "canRotate": false, "canResize": false } ], "shape": "RECTANGLE", "pixelWidth": 1024, "pixelHeight": 600, "dpi": 160, "currentPixelWidth": 1024, "currentPixelHeight": 600, "touch": [ "SINGLE" ], "video": { "codecs": [ "H_264_42", "H_264_41" ] } }, "Viewports": [ { "type": "APL", "id": "main", "shape": "RECTANGLE", "dpi": 160, "presentationType": "STANDARD", "canRotate": false, "configuration": { "current": { "video": { "codecs": [ "H_264_42", "H_264_41" ] }, "size": { "type": "DISCRETE", "pixelWidth": 1024, "pixelHeight": 600 } } } } ] }, "request": { "type": "LaunchRequest", "requestId": "amzn1.echo-api.request.b0de7b26-cfba-4942-92b4-d5589c7b8db3", "timestamp": "2020-03-29T15:21:35Z", "locale": "en-IN", "shouldLinkResultBeReturned": false } }
Azure OCR [printed text] is not reading the receipt lines in the right order
Application Goal: read the receipt image, extract the store/organization name along with the total amount paid. Feed it to web-form for auto-filling & submission. Post Request - "https://*.cognitiveservices.azure.com/vision/v2.0/recognizeText?{params} Get Request - https://*.cognitiveservices.azure.com/vision/v2.0/textOperations/{operationId} however when I get the results back, sometimes it's confusing in line ordering (see below picture [similar results in JSON response]) This mixing is resulting in getting the total as $0.88 Similar situations are present for 2 out of 9 testing receipts. Q: Why it's working for similar & different structured receipts but for some reason not consistent for all? Also, any ideas how to get around it?
I had a quick look to your case. OCR Result As you mentioned, the results are not ordered as you thought. I had a quick look to the bounding boxes values and I don't know how they are ordered. You could try to consolidate fields based on that, but there is a service that is already doing it for you. Form Recognizer: Using Form Recognizer and your image, I got the following results for your receipt. As you can see below, the understandingResults contains the total with its value ("value": 9.11), the MerchantName ("Chick-fil-a") and other fields. { "status": "Succeeded", "recognitionResults": [ { "page": 1, "clockwiseOrientation": 0.17, "width": 404, "height": 1226, "unit": "pixel", "lines": [ { "boundingBox": [ 108, 55, 297, 56, 296, 71, 107, 70 ], "text": "Welcome to Chick-fil-a", "words": [ { "boundingBox": [ 108, 56, 169, 56, 169, 71, 108, 71 ], "text": "Welcome", "confidence": "Low" }, { "boundingBox": [ 177, 56, 194, 56, 194, 71, 177, 71 ], "text": "to" }, { "boundingBox": [ 201, 56, 296, 57, 296, 71, 201, 71 ], "text": "Chick-fil-a" } ] }, ... OTHER LINES CUT FOR DISPLAY ... ] } ], "understandingResults": [ { "pages": [ 1 ], "fields": { "Subtotal": null, "Total": { "valueType": "numberValue", "value": 9.11, "text": "$9.11", "elements": [ { "$ref": "#/recognitionResults/0/lines/32/words/0" }, { "$ref": "#/recognitionResults/0/lines/32/words/1" } ] }, "Tax": { "valueType": "numberValue", "value": 0.88, "text": "$0.88", "elements": [ { "$ref": "#/recognitionResults/0/lines/31/words/0" }, { "$ref": "#/recognitionResults/0/lines/31/words/1" }, { "$ref": "#/recognitionResults/0/lines/31/words/2" } ] }, "MerchantAddress": null, "MerchantName": { "valueType": "stringValue", "value": "Chick-fil-a", "text": "Chick-fil-a", "elements": [ { "$ref": "#/recognitionResults/0/lines/0/words/2" } ] }, "MerchantPhoneNumber": { "valueType": "stringValue", "value": "+13092689500", "text": "309-268-9500", "elements": [ { "$ref": "#/recognitionResults/0/lines/4/words/0" } ] }, "TransactionDate": { "valueType": "stringValue", "value": "2019-06-21", "text": "6/21/2019", "elements": [ { "$ref": "#/recognitionResults/0/lines/6/words/0" } ] }, "TransactionTime": { "valueType": "stringValue", "value": "13:00:57", "text": "1:00:57 PM", "elements": [ { "$ref": "#/recognitionResults/0/lines/6/words/1" }, { "$ref": "#/recognitionResults/0/lines/6/words/2" } ] } } } ] } More details on Form Recognizer: https://azure.microsoft.com/en-us/services/cognitive-services/form-recognizer/
the difference between the following error
when i use nodejs http library(Request) to request target website, i get some error: [{ "response": { "code": "ECONNRESET", "errno": "ECONNRESET", "syscall": "read" } }, { "response": { "code": "ESOCKETTIMEDOUT", "connect": false } }, { "response": { "code": "ETIMEDOUT", "connect": true } }, { "response": { "code": "ETIMEDOUT", "connect": false } }] i want to know the difference between these error.