grpc++: process hang by synchronous stub call , set_deadline not valid? - c++

i ran into a problem , pls help:
What version of gRPC and what language are you using?
libgrpc++.so.1.26.0
What operating system (Linux, Windows,...) and version?
centos7
What did you do?
my scenario is : I have a grpc server named A and, when I receive a grpc message, send the message to another grpc server named B directly;
my server A initial(CRpcNetServer class):
int CRpcNetServer::Initialize()
{
std::string listenAddr = "this is listen address";
ServerBuilder builder;
builder.AddListeningPort(listenAddr, grpc::InsecureServerCredentials());
//register
builder.RegisterService(&AService_); //protobuf definition A
builder.RegisterService(&BService_); //protobuf definition A
//
cq_ = builder.AddCompletionQueue();
server_ = builder.BuildAndStart();
new CallData(&AService_, &BService_, cq_.get(), CallData::S_TYPE_GRPC_MESSAGE);
//new CallData(&AService_, &BService_, cq_.get(), {other message type});
return ERROR_CODE_SUCCESS;
}
void CRpcNetServer::handleRpcs()
{
void *tag;
bool ok;
while (true)
{
if (GPR_UNLIKELY(!(cq_->Next(&tag, &ok))))
{
spdlog::error("handleRpcs||get next message failed, try again");
continue;
}
if (GPR_UNLIKELY(!ok))
{
spdlog::error("handleRpcs||get next message notok, try again");
continue;
}
static_cast<CallData *>(tag)->process();
}
}
when message arrived(CallData class):
void CallData::process()
{
if (status_ == CREATE)
{
status_ = PROCESS;
switch (s_type_)
{
case S_TYPE_GRPC_MESSAGE:
BService_->RequestOnMessage(&ctx_, &GrpcUpLinkMessage, &processGrpcUplinkResponse, cq_, cq_, this);
//case other message type
default:
break;
}
}
else if (status_ == PROCESS)
{
status_ = FINISH;
new CallData(AService_, BService_, cq_, this->s_type_);
switch (s_type_)
{
case S_TYPE_GRPC_UPLINK_MESSAGE:
{
Status ret = this->onGrpcUplinkMessage(gRPCUpLinkMessage, emptyResponse_);
processGrpcUplinkResponse.Finish(emptyResponse_, ret, this);
}
break;
default:
break;
}
}
else
{
GPR_ASSERT(status_ == FINISH);
delete this;
}
}
when i received a grpc message, send it to another grpc server directly:
//init grpc client:
CRpcNetClient::CRpcNetClient(){
std::shared_ptr<Channel> channel = grpc::CreateChannel({B server address}, grpc::InsecureChannelCredentials());
stub_ = BServerApi::SendToBDownlinkService::NewStub(channel);
}
//send
std::chrono::time_point<std::chrono::system_clock> deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(100);
ClientContext context;
context.set_deadline(deadline);
std::time_t timestamp = getTimestamp();
Status status = stub_->publishMessage(&context, downLinkGroupRequest, &downLinkGroupResponse);
// process will hang here
std::chrono::time_pointstd::chrono::system_clock deadline = std::chrono::system_clock::now() + std::chrono::milliseconds(100);
I tried to set milliseconds to 1ms, it will return failed , so I think the param is worked, but while set it to 100, it will occurs some time (not inevitable).

Related

pthread_join hangs forever C++

I am running this g_test where I simply initialize and close a client.
TEST(safIpc, createAndCloseClient)
{
std::shared_ptr<fnv::ipcsvc::IpcSvc> safIpc = std::make_shared<fnv::ipcsvc::IpcSvc>();
const std::string& app1 {"/testApp1"};
const std::string& groupName {"wir_clients"};
fnv::ipcsvc::IpcSvcAttrMq attr(fnv::ipcsvc::IpcSvcAttrType::MQ_CLIENT,
app1,
groupName,
"/server");
std::shared_ptr<IpcSvcTestSafHandler> msgHandler = std::make_shared<IpcSvcTestSafHandler>();
// initialize the ipc library
IpcSvcPriv::SharedPtr ipcPrivData {nullptr};
fnv::ipcsvc::IpcSvcRet ret = safIpc->init(attr, msgHandler, ipcPrivData);
EXPECT_EQ(ret, fnv::ipcsvc::IpcSvcRet::SUCCESS);
EXPECT_NE(ipcPrivData, nullptr);
ret = safIpc->close(ipcPrivData, app1); //HANGS here
EXPECT_EQ(fnv::ipcsvc::IpcSvcRet::SUCCESS, ret);
}
In init I create 3 threads: (here is the relevant part of the init code):
1- A process thread
2- a Receive thread
3- A timer thread
int rc = pthread_create(&m_timerThread,
NULL,
&IpcSvcImpl::timer_start,
this);
if (rc != 0)
{
ipcSvcLog(LOGE, "Failed to create timer thread!");
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_timerThread,
"IpcSvcTimerThread");
}
// Start the worker threads
int rc = pthread_create(&m_receiveThread,
NULL,
&IpcSvcImpl::receive,
this);
if (rc != 0)
{
//TODO some error log
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_receiveThread,
"IpcSvcReceiveThread");
rc = pthread_create(&m_processThread,
NULL,
&IpcSvcImpl::process,
this);
if (rc != 0)
{
//TODO some error log
close(tmpPrivData,
attr.getAppId());
return error;
}
pthread_setname_np(m_processThread,
"IpcSvcProcessThread");
Here is the close function:
IpcSvcRet IpcSvcImpl::close(IpcSvcPriv::SharedPtr privateData,
const std::string& appId)
{
if (!privateData)
{
//TODO log about client not providing sane private data
return IpcSvcRet::FAIL;
}
// acquire the mutex and set close called to true
{
std::lock_guard<std::mutex> guard(m_closeMtx);
m_closed = true;
}
if (m_msgQueue)
{
m_msgQueue->mutexInit();
// writing dummy message to process thread
std::pair<std::array<uint8_t, IPCSVC_MAX_MSG_SIZE>, ssize_t> queueMsg;
m_msgQueue->enqueue(queueMsg);
}
// writing dummy message to receive thread
uint32_t buffer = 0;
sendData(privateData,
(void*)&buffer,
sizeof(uint32_t),
appId);
pthread_join(m_receiveThread,
NULL);
pthread_join(m_processThread,
NULL);
if (m_isClient)
{
m_cv.notify_one();
printf("timer thread hangs\n"); // HANGS HERE ///////////////////////////////////////
pthread_join(m_timerThread,
NULL);
//This line is never reached..
}
delete m_msgQueue;
m_msgQueue = nullptr;
// close the ipc layer
if (m_ipc)
{
m_ipc->close();
delete m_ipc;
m_ipc = nullptr;
}
m_clientsList.clear();
m_hbManager = { };
return IpcSvcRet::SUCCESS;
}
Here is the timer_start function:
The timer thread is a timer that is keeps looping forever unless the fc->m_closed is set to true. It triggers fc->timerExpiry() every 2 seconds.
// timer thread entry
void* IpcSvcImpl::timer_start(void *arg)
{
if (!arg)
{
return nullptr;
}
printf("starting timer\n");
IpcSvcImpl* fc = static_cast<IpcSvcImpl *>(arg);
std::unique_lock<std::mutex> lock(fc->m_closeMtx);
while (!(fc->m_closed))
{
printf("Entering loop\n");
lock.unlock();
auto expireAt = std::chrono::steady_clock::now() +
std::chrono::seconds(fc->getTimerInterval());
fc->timerExpiry();
lock.lock();
printf("here?\n");
fc->m_cv.wait_until(lock, expireAt);
printf("Here 2\n");
}
printf("Exited loop\n\n");
return nullptr;
}
The output of the unittest:
[----------] 5 tests from safIpc
[ RUN ] safIpc.createAndCloseClient
starting timer
Entering loop
closing..
timer thread hangs
pthread join hangs forever, I am not sure why. The "here" prints are never hit, which seems odd.
Thanks for the help!

How can i accept RakNet Connecting request in c++?

I want accept client's connecting request but i don't know how can i do this.
Serverside :
enum GameMessages
{
ID_GAME_MESSAGE_1 = ID_USER_PACKET_ENUM + 1
};
using namespace std;
int main(void)
{
RakNet::RakPeerInterface *peer = RakNet::RakPeerInterface::GetInstance();
bool isServer;
RakNet::Packet *packet;
RakNet::SocketDescriptor sd(SERVER_PORT, 0);
peer->Startup(MAX_CLIENTS, &sd, 1);
isServer = true;
if (isServer)
{
printf("Sunucu baslatiliyor.\n");
// We need to let the server accept incoming connections from the clients
peer->SetMaximumIncomingConnections(MAX_CLIENTS);
}
while (1)
{
for (packet = peer->Receive(); packet; peer->DeallocatePacket(packet), packet = peer->Receive())
{
switch (packet->data[0])
{
case ID_REMOTE_DISCONNECTION_NOTIFICATION:
printf("Another client has disconnected.\n");
break;
case ID_REMOTE_CONNECTION_LOST:
printf("Another client has lost the connection.\n");
break;
case ID_REMOTE_NEW_INCOMING_CONNECTION:
printf("Another client has connected.\n");
break;
case ID_CONNECTION_REQUEST_ACCEPTED:
{
printf("Our connection request has been accepted.\n");
// Use a BitStream to write a custom user message
// Bitstreams are easier to use than sending casted structures, and handle endian swapping automatically
RakNet::BitStream bsOut;
bsOut.Write((RakNet::MessageID)ID_GAME_MESSAGE_1);
bsOut.Write("Oyuna hosgeldin emmolu.");
peer->Send(&bsOut, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, false);
}
break;
case ID_NEW_INCOMING_CONNECTION:
printf("Bir baglanti geliyor.\n");
break;
case ID_NO_FREE_INCOMING_CONNECTIONS:
printf("The server is full.\n");
break;
case ID_DISCONNECTION_NOTIFICATION:
if (isServer) {
printf("A client has disconnected.\n");
}
else {
printf("We have been disconnected.\n");
}
break;
case ID_CONNECTION_LOST:
if (isServer) {
printf("A client lost the connection.\n");
}
else {
printf("Connection lost.\n");
}
break;
case ID_GAME_MESSAGE_1:
{
RakNet::RakString rs;
RakNet::BitStream bsIn(packet->data, packet->length, false);
bsIn.IgnoreBytes(sizeof(RakNet::MessageID));
bsIn.Read(rs);
printf("%s\n", rs.C_String());
}
break;
default:
printf("Message with identifier %i has arrived.\n", packet->data[0]);
break;
}
}
}
RakNet::RakPeerInterface::DestroyInstance(peer);
return 0;
}
When i try my work it's giving me .
[LOG]
Server : Server started.
Client : Sent request to connect server.
Server : A request received from client to connect server.
Server : Accept client's request. ( What i'm trying to do )

How to set timeout on socket receive vc++ mfc

I have created a server in MFC. Client is connected to server and server is waiting for receiving data, which is sent by the client.
I want a timeout period for receiving pSocket.Receive(cbuf,1).
Here is my code :
int i_userid; AfxSocketInit(); bool bRun = true;
CWinThread *pCurrentThread; pCurrentThread = AfxGetThread();
SOCKET pCurrentHandle; CSocket pSocket; pCurrentHandle =hClinetHandle;
pSocket.Attach(hClinetHandle);
LeaveCriticalSection(&m_socket_lock); CSocket t_socket;
CString m_Ipadd=L""; UINT m_portno=0;
pSocket.GetPeerName(m_Ipadd,m_portno);
st_Client* m_st_Client=new st_Client();
//receive Use Id and Get UserPortfolio CString m_token=L"";
CString New_data=L"";char cbuf[24];
for(int i=0;i<24;i++)
cbuf[i] ='\0';
while(bRun)
{
if(pSocket.Receive(cbuf,1)>0)
{
New_data=cbuf;
if(wcscmp(New_data,L"\r")==0 ||wcscmp(New_data,L"|")==0)
{
break;
}
m_token=m_token+New_data;
}
else
{
bRun=false;
break;
}
}
some other code of CTimeout but it didn't work there.........
void CServerSocket::OnAccept(int nErrorCode)
{
m_Client.m_hSocket = INVALID_SOCKET;
AfxMessageBox("Client Request Connection");
if(!SetTimeOut(10000))
{
ASSERT(FALSE);
// Error Handling...for some reason, we could not setup
// the timer.
}
if(!Accept(m_Client))
{
int nError = GetLastError();
if(nError==WSAEINTR)
AfxMessageBox("No Connections Arrived For 10 Seconds");
else
; // Do other error processing.
}
CSocket::OnAccept(nErrorCode);
}

SSL_accept takes 200ms (c / openssl)

Is it normal that SSL_accept(ssl) takes 200 ms?
Running as a windows service, written in c++, using MFC and Boost. Running on an intel xeon e5620 2.4G, with 4GB memory, and Win 7 Pro.
Following is my code. I meanwhile suspected that maybe other methods before SSL_accept (SSL_CTX_* RAND_* etc) might consume long time , but I logged everthing and discovered that SSL_accept is eating all the time.
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
{
return preverify_ok;
}
void somemethod() {
SSL *ssl = 0;
SSL_CTX *tlsctx = 0;
int ret_conn = -1;
tlsctx = SSL_CTX_new( SSLv23_method());
SSL_CTX_use_certificate_file(tlsctx, sCert , SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(tlsctx, sKey , SSL_FILETYPE_PEM);
RAND_write_file(sRandomPem);
int _rand_loaded = RAND_load_file(sRandomPem, -1 );
if(! SSL_CTX_load_verify_locations(tlsctx, sCACert, NULL))
{
// TODO // /* Handle error here */
}
SSL_CTX_set_verify( tlsctx, SSL_VERIFY_PEER, verify_callback );
ssl = SSL_new(tlsctx);
int _error = SSL_ERROR_WANT_READ;
int loopCount = 0;
// START MEASURING TIME FROM HERE
SSL_set_fd(ssl, _sck);
while(ret_conn != 1 )
{
loopCount++;
ret_conn = SSL_accept(ssl);
_error = SSL_get_error(ssl, ret_conn);
switch (_error)
{
case SSL_ERROR_NONE:
break;
case SSL_ERROR_WANT_WRITE:
break;
case SSL_ERROR_WANT_READ:
break;
case SSL_ERROR_WANT_X509_LOOKUP:
break;
case SSL_ERROR_SYSCALL:
break;
case SSL_ERROR_SSL:
break;
case SSL_ERROR_ZERO_RETURN:
break;
}
if( _error == SSL_ERROR_WANT_READ || _error == SSL_ERROR_WANT_WRITE)
{
Sleep(1);
} else
{
break;
}
}
if( ret_conn < 1)
{
Log("SSL_accept -1 ", ERR_error_string(_error, NULL));
return;
}
// MEASURING END HERE, takes ~200ms (on successfully accepting connection)
}
To my knowledge, SSL_accept is a blocking function, which waits for your client to connect. If your client connect 200 ms later than the beginning for the SSL_accept call, then you will measure that waiting time.

My service won't stop

Whenever I try to stop my service through the services manager, I get the following error and the service stays in a started state. "Could not stop the service on Local Computer. The service did not return an error. This could be an internal Windows error or an internal service error."
I've had such trouble with this issue that I tried to follow the logic from Microsoft as best as I could.
http://msdn.microsoft.com/en-us/library/windows/desktop/bb540474(v=vs.85).aspx
There is a similar issue with this in .Net 1.1 that you'll find if you search; however, I'm not using the framweork at all.
void WINAPI serviceCtrlHandler(DWORD dwCtrl )
{
switch(dwCtrl)
{
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
SetEvent(stopEvent);
ReportSvcStatus(serviceStatus->dwCurrentState, NO_ERROR, 0);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
void WINAPI startMain(DWORD argc, LPTSTR *argv)
{
serviceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, serviceCtrlHandler);
serviceStatus->dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus->dwServiceSpecificExitCode = NO_ERROR;
if (serviceStatusHandle == 0)
{
debug->DebugMessage(L"RegisterServiceCtrlHandler() failed, error: " + Error::GetErrorMessageW(GetLastError()));
return;
}
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
if (!SetServiceStatus(serviceStatusHandle, serviceStatus))
{
//debug->DebugMessage(L"SetserviceStatus() failed, error: " + Error::GetErrorMessageW(GetLastError()));
//return;
}
stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
boost::thread dust_main_thread(dust_main);
while(1)
{
WaitForSingleObject(stopEvent, INFINITE);
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
}
VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
serviceStatus->dwCurrentState = dwCurrentState;
serviceStatus->dwWin32ExitCode = dwWin32ExitCode;
serviceStatus->dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
serviceStatus->dwControlsAccepted = 0;
else serviceStatus->dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
serviceStatus->dwCheckPoint = 0;
else
serviceStatus->dwCheckPoint = dwCheckPoint++;
SetServiceStatus(serviceStatusHandle, serviceStatus);
}
Run the service and then attach the debugger to the running process. Put a breakpoint at the serviceCtrlHandler and after the WaitForSingleObject(stopEvent, INFINITE) -- make sure what you think should happen does.