gsource is automatically restored when a problem occurs in eventfd. 36/231436/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Tue, 21 Apr 2020 09:30:15 +0000 (18:30 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Tue, 21 Apr 2020 09:30:18 +0000 (18:30 +0900)
 - Problems caused from other libraries that attempt to use the wrong fd
  often affect the eventfd of surf_source or del_source.
 - In such a case, in the past, assert checking was used to generate abort
  and it was not good.
 - So I made it possible to regenerate eventfd to minimize
  the abort generated by libtpl-egl and overcome the problem situation.

Change-Id: I4cb23a022b40c48f864de402f3beabd2fec29a64
Signed-off-by: Joonbum Ko <joonbum.ko@samsung.com>
src/tpl_wayland_egl_thread.c

index 2742986fc1abd8df5c7a4e6217a22eb535e20bbe..f5d8bc34801e45bfe5a9c2ea1e82e17c1109f2f6 100755 (executable)
@@ -248,6 +248,7 @@ static gboolean
 _twe_thread_del_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
 {
        twe_del_source *del_source = (twe_del_source *)source;
+       tpl_result_t res = TPL_ERROR_NONE;
        GIOCondition cond;
 
        g_mutex_lock(&_twe_ctx->thread_mutex);
@@ -259,20 +260,39 @@ _twe_thread_del_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                uint64_t u;
 
                s = read(del_source->event_fd, &u, sizeof(uint64_t));
-               if (s != sizeof(uint64_t))
+               if (s != sizeof(uint64_t)) {
                        TPL_ERR("Failed to read from event_fd(%d)",
                                        del_source->event_fd);
+                       res = TPL_ERROR_INVALID_CONNECTION;
+               }
 
                if (del_source->destroy_target_source_func)
                        del_source->destroy_target_source_func(del_source->target_source);
-       } else {
+       }
+
+       if (cond && !(cond & G_IO_IN)) {
                TPL_ERR("eventfd(%d) cannot wake up with other condition. cond(%d)",
                                del_source->event_fd, cond);
+               res = TPL_ERROR_INVALID_CONNECTION;
+       }
+
+       if (res != TPL_ERROR_NONE) {
+               g_source_remove_unix_fd(source, del_source->tag);
+
+               TPL_WARN("event_fd(%d) of del_source(%p) has been closed. it will be recreated.",
+                                del_source->event_fd, del_source);
 
-               g_source_remove_unix_fd(del_source->event_fd, del_source->tag);
                close(del_source->event_fd);
-               del_source->tag = NULL;
-               del_source->event_fd = -1;
+
+               del_source->event_fd = eventfd(0, EFD_CLOEXEC);
+               if (del_source->event_fd < 0) {
+                       TPL_ERR("Failed to create eventfd. errno(%d)", errno);
+               } else {
+                       del_source->tag = g_source_add_unix_fd(&del_source->gsource,
+                                                                                                       del_source->event_fd,
+                                                                                                       G_IO_IN);
+               }
+               TPL_DEBUG("[RECREATED] eventfd(%d) tag(%p)", del_source->event_fd, del_source->tag);
        }
 
        g_cond_signal(&_twe_ctx->thread_cond);
@@ -2328,6 +2348,7 @@ static gboolean
 _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data)
 {
        twe_wl_surf_source *surf_source = (twe_wl_surf_source *)source;
+       tpl_result_t res = TPL_ERROR_NONE;
        GIOCondition cond;
 
        g_mutex_lock(&surf_source->surf_mutex);
@@ -2339,19 +2360,37 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                uint64_t u;
 
                s = read(surf_source->event_fd, &u, sizeof(uint64_t));
-               if (s != sizeof(uint64_t))
+               if (s != sizeof(uint64_t)) {
                        TPL_ERR("Failed to read from event_fd(%d)",
                                        surf_source->event_fd);
+                       res = TPL_ERROR_INVALID_CONNECTION;
+               }
 
                _twe_thread_wl_surface_acquire_and_commit(surf_source);
 
-       } else {
+       }
+
+       if (cond && !(cond & G_IO_IN)) {
                TPL_ERR("eventfd(%d) cannot wake up with other condition. cond(%d)",
                                surf_source->event_fd, cond);
+               res = TPL_ERROR_INVALID_CONNECTION;
+       }
+
+       if (res != TPL_ERROR_NONE) {
                g_source_remove_unix_fd(source, surf_source->tag);
                close(surf_source->event_fd);
-               surf_source->tag = NULL;
-               surf_source->event_fd = -1;
+
+               TPL_WARN("event_fd of surf_source(%p) has been closed. it will be recreated.",
+                                surf_source);
+               surf_source->event_fd = eventfd(0, EFD_CLOEXEC);
+               if (surf_source->event_fd < 0) {
+                       TPL_ERR("Failed to create eventfd. errno(%d)", errno);
+               } else {
+                       surf_source->tag = g_source_add_unix_fd(&surf_source->gsource,
+                                                                                                       surf_source->event_fd,
+                                                                                                       G_IO_IN);
+               }
+               TPL_DEBUG("[RECREATED] eventfd(%d) tag(%p)", surf_source->event_fd, surf_source->tag);
        }
 
        g_mutex_unlock(&surf_source->surf_mutex);