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 8732a7da5d34c715b8af4839d64e038e7f9bd42d..fc708504ac786914febbb67ff8e5f9eaa0724989 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 5bb61653829c4fc8452f0947ba7e0e1ff77b19a9..d5f56f04bd68749b0f71dcec1e24063acc53e1c8 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 22774dae2af5c6058891879e9ff0a0815ebd1643..319f21e021bb589e64052a5de0ffa78634c1f7f0 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;