Call poll() again when it fails with an EAGAIN error 35/232035/15
authorYoungHun Kim <yh8004.kim@samsung.com>
Mon, 27 Apr 2020 22:49:24 +0000 (07:49 +0900)
committerYoungHun Kim <yh8004.kim@samsung.com>
Mon, 11 May 2020 04:38:15 +0000 (13:38 +0900)
 - poll() can fail with the error EAGAIN if the system fails to allocate kernel-internal
   resources. Portable programs may wish to check for EAGAIN and loop.
 - Change the mode of mm_resource_manager_daemon_priv.c
 - Update some logs

Change-Id: I2ee8f16931b14e57ed065be607b08d9d81f1b4ca

src/daemon/mm_resource_manager_daemon_dbus.c [changed mode: 0755->0644]
src/daemon/mm_resource_manager_daemon_priv.c
src/lib/mm_resource_manager_priv.c

old mode 100755 (executable)
new mode 100644 (file)
index 71298d9..63017a7 100644 (file)
@@ -95,6 +95,7 @@ static void __handle_release_callbacks(GArray *requests);
 static inline void __add_cb_request(GArray *cb_requests, mm_resource_manager_dmn_p mgr,
                mm_resource_manager_res_type_e type, mm_resource_manager_res_volume volume);
 static void __release_all_resources(mm_resource_manager_dmn_s *manager);
+static gboolean __poll(struct pollfd sync);
 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id);
 
 
@@ -766,9 +767,38 @@ static void __release_all_resources(mm_resource_manager_dmn_s *manager)
        }
 }
 
+static gboolean __poll(struct pollfd sync)
+{
+       int errsv = 0;
+       int try_cnt = 0;
+       int ret = 0;
+
+       while (try_cnt++ < 3) {
+               sync.events = POLLIN;
+               sync.revents = 0;
+
+               ret = poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000);
+
+               if (ret == -1) {
+                       errsv = errno;
+                       MM_RM_ERROR("Polling is failed [fd %d errno %d]", sync.fd, errsv);
+                       if (errsv == EAGAIN)
+                               continue;
+                       break;
+               } else if (ret == 0) {
+                       MM_RM_WARNING("Wait timeout is elapsed [fd %d]", sync.fd);
+                       break;
+               }
+
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
 static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id)
 {
-       gboolean ret = TRUE;
+       gboolean ret = FALSE;
        struct pollfd sync = {0};
        mm_resource_manager_id recv_id;
        ssize_t read_size;
@@ -776,37 +806,23 @@ static gboolean __wait_for_release_cb_sync(mm_resource_manager_id id)
        sync.fd = open(RELEASE_CB_SYNC_PATH, O_RDONLY | O_NONBLOCK);
        MM_RM_RETVM_IF(sync.fd == -1, FALSE, "Sync FIFO cannot be opened");
 
-       sync.events = POLLIN;
-       switch (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000)) {
-       case -1:
-               MM_RM_ERROR("Polling is failed");
-               ret = FALSE;
-               break;
-       case 0:
-               MM_RM_DEBUG("Wait timeout is elapsed");
-               ret = FALSE;
-               break;
-       default:
-               read_size = read(sync.fd, &recv_id, sizeof(recv_id));
-               if (read_size == sizeof(recv_id)) {
-                       ret = id == _mm_rm_hash64(recv_id);
-                       if (ret == FALSE)
-                               MM_RM_ERROR("Sync is received from wrong client #%"PRIu64, id);
-                       /*
-                        * Wait POLLHUP to avoid situation when client sent last sync
-                        * through the pipe, but not already closed the pipe handle and
-                        * the daemon is already opened the pipe again and waiting for
-                        * the next sync.
-                        */
-                       sync.revents = 0;
-                       if (poll(&sync, 1, RELEASE_CB_SYNC_TIMEOUT * 1000) == 0 || (sync.revents & (POLLHUP | POLLERR)) == 0)
-                               MM_RM_ERROR("The client didn't close the FIFO");
-               } else {
-                       MM_RM_ERROR("Read is failed (revents=%hd,read_size=%zd)", sync.revents, read_size);
-                       ret = FALSE;
-               }
+       if (!__poll(sync))
+               goto out;
+
+       read_size = read(sync.fd, &recv_id, sizeof(recv_id));
+       if (read_size != sizeof(recv_id)) {
+               MM_RM_ERROR("Read is failed (revents=%hd, read_size=%zd)", sync.revents, read_size);
+               goto out;
        }
 
+       if (id != _mm_rm_hash64(recv_id)) {
+               MM_RM_ERROR("Sync is received from wrong client #%"PRIu64, id);
+               goto out;
+       }
+
+       ret = __poll(sync);
+
+out:
        close(sync.fd);
 
        return ret;
index 5e43657..6ce9630 100644 (file)
@@ -394,7 +394,7 @@ int _mm_resource_manager_get_resource_info(mm_resource_manager_h rm,
        MM_RM_UNLOCK_RETVM_IF(i == MM_RESOURCE_MANAGER_RES_NOT_FOUND,
                        handle->resources_lock,
                        MM_RESOURCE_MANAGER_ERROR_INVALID_PARAMETER,
-                       "Invalid resource handle");
+                       "Invalid resource handle #%"PRIu64"", _mm_rm_hash64(handle->id));
 
        info->type = resource->type;
        info->volume = resource->volume;
@@ -766,10 +766,7 @@ static int __dbus_init_conf(mm_resource_manager_s *handle)
                        MM_RESOURCE_MANAGER_ERROR_INVALID_OPERATION, "Variant data are empty");
 
        if (g_variant_iter_init(&volume_iter, max_volume) == MM_RESOURCE_MANAGER_RES_TYPE_MAX) {
-               for (i = 0; g_variant_iter_next(&volume_iter, "i", &handle->__max_resource_volumes[i]); i++) {
-                       if (handle->__max_resource_volumes[i] == MM_RESOURCE_MANAGER_NO_RES)
-                               MM_RM_INFO("Maybe occur the  error operation related dbus");
-               }
+               for (i = 0; g_variant_iter_next(&volume_iter, "i", &handle->__max_resource_volumes[i]); i++);
                g_variant_unref(max_volume);
                max_volume = NULL;
        } else {