libjson-rpc-cpp
libjson-rpc-cpp copied to clipboard
Potential race condition on socket open/send (discovered on M1)
Hello,
I am finding that I have the following race condition:
in server/connectors/unixdomainsocketserver.cpp
we have:
bool UnixDomainSocketServer::InitializeListener() {
...
// Set to non-blocking mode
fcntl(this->socket_fd, F_SETFL, FNDELAY);
So a non blocking socket is created.
Later, a connection is opened when I send data to it, and this function is called:
void UnixDomainSocketServer::HandleConnection(int connection) {
string request, response;
StreamReader reader(DEFAULT_BUFFER_SIZE);
reader.Read(request, connection, DEFAULT_DELIMITER_CHAR);
...
close(connection);
The read is as following:
bool StreamReader::Read(std::string &target, int fd, char delimiter) {
ssize_t bytesRead;
do {
bytesRead = read(fd, this->buffer, buffersize);
if (bytesRead < 0) {
return false;
} else {
target.append(buffer, static_cast<size_t>(bytesRead));
}
} while (memchr(buffer, delimiter, bytesRead) ==
NULL); //(target.find(delimiter) == string::npos && bytesRead > 0);
target.pop_back();
return true;
}
So what happens is that if the HandleConnection call is executed fast enough, the client has not yet sent any data. Since the socket is non-blocking, the streamreader read returns -1, and the request string will be an empty string. The method then closes the connection, causing an error for the client who is trying to send data.
The current best solution I have to this is to increase the timeout in the handler dispatch. However, it would be better I think if either the socket was blocking, or the return value from the stream reader was utilized in order to detect this case.