Use MSG_DONTWAIT flag 08/266408/3
authorHwankyu Jhun <h.jhun@samsung.com>
Thu, 11 Nov 2021 15:41:23 +0000 (00:41 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Thu, 11 Nov 2021 22:48:38 +0000 (07:48 +0900)
This patch uses MSG_DONTWAIT flag instead of socket existence check.
If calling the send() function returns an error with the errno value
that is EAGAIN or EWOULDBLOCK, the method will call the sleep() and try
to send the data again.
The interval is 2ms. The maximum retry count is 10.
If the retry count exceeds 10 times, AMD will close the file descriptor
to disconnect the connection. When handling the disconnected event,
AMD doesn't invoke the disconnected event callback function if the
client socket is closed. It means the connection is closed by AMD forcedly.

Change-Id: I8217d889506d82418c271d79491817634b33e32d
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
src/lib/amd_app_request_broker.cc
src/lib/amd_launch.c
src/lib/socket/client_socket.cc

index 8732a7d..fc70850 100644 (file)
@@ -192,8 +192,10 @@ class AppRequestBroker {
     if (found == channels_.end())
       return;
 
+    auto& client_channel = found->second;
+    bool is_closed = client_channel->IsClosed();
     channels_.erase(found);
-    if (disconn_cb_)
+    if (!is_closed && disconn_cb_)
       disconn_cb_(pid, disconn_data_);
   }
 
@@ -295,8 +297,11 @@ int _app_request_broker_send(app_request_t* request,
 
   auto raw = parcel.GetRaw();
   int ret = channel->Send(reinterpret_cast<void*>(&raw[0]), raw.size());
-  if (ret != 0)
+  if (ret != 0) {
+    _E("Socket will be closed, pid(%d)", channel->GetPid());
+    channel->Close();
     return ret;
+  }
 
   if (callback)
     channel->Push(std::make_shared<ResultCb>(callback, user_data));
@@ -316,8 +321,11 @@ int _app_request_broker_connect(pid_t pid, uid_t uid) {
   parcel.WriteInt32(AUL_SOCK_ASYNC);
   auto raw = parcel.GetRaw();
   int ret = channel->Send(reinterpret_cast<void*>(&raw[0]), raw.size());
-  if (ret != 0)
+  if (ret != 0) {
+    _E("Socket will be closed. pid(%d)", pid);
+    channel->Close();
     return ret;
+  }
 
   broker.AddClientChannel(pid, channel);
   return 0;
index 5bb6165..d5f56f0 100644 (file)
@@ -497,9 +497,6 @@ static int __send_app_request(pid_t pid, uid_t uid, int cmd, int clifd,
                .data = data
        };
 
-       if (!_app_status_socket_exists(_app_status_find(pid)))
-               return -ECOMM;
-
        info = __create_reply_info(pid, uid, cmd, clifd, data);
        if (!info)
                return -ENOMEM;
index 22774da..319f21e 100644 (file)
 #include <unistd.h>
 
 namespace amd {
+namespace {
+
+constexpr const int MAX_RETRY_CNT = 10;
+
+}  // namespace
 
 ClientSocket::ClientSocket() {
   fd_ = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
@@ -71,9 +76,19 @@ void ClientSocket::Connect(const std::string& endpoint) {
 int ClientSocket::Send(const void* buf, unsigned int size) {
   const unsigned char* buffer = static_cast<const unsigned char*>(buf);
   size_t len = size;
+  int retry_cnt = MAX_RETRY_CNT;
   while (len) {
-    ssize_t bytes = send(fd_, buffer, len, MSG_NOSIGNAL);
+    ssize_t bytes = send(fd_, buffer, len, MSG_NOSIGNAL | MSG_DONTWAIT);
     if (bytes < 0) {
+      if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
+        if (retry_cnt > 0) {
+          retry_cnt--;
+          _E("send(): fd(%d), errno(%d). sleep and retry ...", fd_, errno);
+          usleep(2 * 1000);
+          continue;
+        }
+      }
+
       int ret = -errno;
       _E("send() is failed. fd(%d), errno(%d)", fd_, errno);
       return ret;