I have a server that’s currently using asynchronous IO to (1) accept data from cin and send that input across a UNIX socket and (2) accept data on a UNIX socket, parse that data, and send back a response.
When I’m parsing the data, how can I block the I/O that occurs in the parser (ParseJSON(data_.data()) in the example below)? It should ask questions and collect answers to those questions via cin before returning parsed for the async_write; currently, the questions are printed, but the response is sent before the answers are input to cin.
socket_ is a stream_protocol::socket from boost::asio, FWIW.
void handle_read(const boost::system::error_code& error,
size_t bytes_transferred)
{
if (!error)
{
string parsed = ParseJSON(data_.data());
async_write(socket_,
buffer(parsed),
boost::bind(&session::handle_write,
shared_from_this(),
placeholders::error));
}
}
void handle_write(const boost::system::error_code& error)
{
if (!error)
{
socket_.async_read_some(buffer(data_),
boost::bind(&session::handle_read,
shared_from_this(),
placeholders::error,
placeholders::bytes_transferred));
}
}
An abbreviated version of what happens in ParseJSON (Some strings replaced with <> for confidentiality):
string ParseJSON(string input)
{
int status;
string toWrite;
JSONNode parsed = libjson::parse(input);
JSONNode::const_iterator iter = parsed.begin();
json_string node_name = iter -> as_string();
if (node_name.compare("<>") == 0)
{
cout << "<>" << endl;
cout << "<>";
cout.flush();
cin >> status;
JSONNode n(JSON_NODE);
n.push_back(JSONNode("<>","<>"));
JSONNode c(JSON_NODE);
c.set_name("args");
c.push_back(JSONNode("<>",status));
n.push_back(c);
toWrite = n.write();
return toWrite;
}
}
If
ParseJSON()does a blocking read fromcinthen it will block which means thathandle_read()won’t execute theasync_write()untilParseJSON()returns.I think the problem is that
parsedis a stack variable.handle_read()will most likely return before the data is actually written andparsedwill be destroyed. The data passed toasync_write()needs to be valid until the completion handler (handle_write) is called.If
handle_read()and andhandle_write()are member functions you could add aparsedmember to hold the data. Alternatively, you could wrapparsedin shared_ptr that is bound tohandle_write()something like this:When the completion handler exits, the last reference to the shared_ptr will disappear and
pswill be destroyed.