Fix gem memory leak issue when client destroyed. 27/255727/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Tue, 23 Mar 2021 04:44:38 +0000 (13:44 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Tue, 23 Mar 2021 04:44:41 +0000 (13:44 +0900)
 - When surface_fini, the ENQUEUED state, the wl_egl_buffer
  was not properly processed.
 - As a result, the APP was terminated without
  tbm_surface_destroy, resulting in GEM Memory leak.

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

index bd4ba82..a07ba40 100755 (executable)
@@ -1838,6 +1838,7 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface)
        tpl_wl_egl_buffer_t *wl_egl_buffer      = NULL;
        tpl_bool_t need_to_release              = TPL_FALSE;
        tpl_bool_t need_to_cancel               = TPL_FALSE;
+       buffer_status_t status                  = RELEASED;
        int idx                                 = 0;
 
        while (wl_egl_surface->buffer_cnt) {
@@ -1859,32 +1860,23 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface)
 
                tpl_gmutex_lock(&wl_egl_buffer->mutex);
 
+               status = wl_egl_buffer->status;
+
                TPL_DEBUG("[idx:%d] wl_egl_buffer(%p) tbm_surface(%p) status(%s)",
                                  idx, wl_egl_buffer,
                                  wl_egl_buffer->tbm_surface,
-                                 status_to_string[wl_egl_buffer->status]);
+                                 status_to_string[status]);
 
-               /* ACQUIRED, WAITING_SIGNALED, WAITING_VBLANK, COMMITTED */
-               /* It has been acquired but has not yet been released, so this
-                * buffer must be released. */
-               need_to_release = (wl_egl_buffer->status == ACQUIRED ||
-                                                  wl_egl_buffer->status == WAITING_SIGNALED ||
-                                                  wl_egl_buffer->status == WAITING_VBLANK ||
-                                                  wl_egl_buffer->status == COMMITTED);
-               /* After dequeue, it has not been enqueued yet
-                * so cancel_dequeue must be performed. */
-               need_to_cancel = wl_egl_buffer->status == DEQUEUED;
-
-               if (wl_egl_buffer->status >= ENQUEUED) {
+               if (status >= ENQUEUED) {
                        tpl_bool_t need_to_wait  = TPL_FALSE;
                        tpl_result_t wait_result = TPL_ERROR_NONE;
 
                        if (!wl_egl_display->use_explicit_sync &&
-                               wl_egl_buffer->status < WAITING_VBLANK)
+                               status < WAITING_VBLANK)
                                need_to_wait = TPL_TRUE;
 
                        if (wl_egl_display->use_explicit_sync &&
-                               wl_egl_buffer->status < COMMITTED)
+                               status < COMMITTED)
                                need_to_wait = TPL_TRUE;
 
                        if (need_to_wait) {
@@ -1893,12 +1885,24 @@ _tpl_wl_egl_surface_buffer_clear(tpl_wl_egl_surface_t *wl_egl_surface)
                                                                                                  &wl_egl_buffer->mutex,
                                                                                                  16); /* 16ms */
                                tpl_gmutex_lock(&wl_egl_display->wl_event_mutex);
+
+                               status = wl_egl_buffer->status;
+
                                if (wait_result == TPL_ERROR_TIME_OUT)
                                        TPL_WARN("timeout occured waiting signaled. wl_egl_buffer(%p)",
                                                         wl_egl_buffer);
                        }
                }
 
+               /* ACQUIRED, WAITING_SIGNALED, WAITING_VBLANK, COMMITTED */
+               /* It has been acquired but has not yet been released, so this
+                * buffer must be released. */
+               need_to_release = (status >= ACQUIRED && status <= COMMITTED);
+
+               /* After dequeue, it has not been enqueued yet
+                * so cancel_dequeue must be performed. */
+               need_to_cancel = (status == DEQUEUED);
+
                if (need_to_release) {
                        tsq_err = tbm_surface_queue_release(wl_egl_surface->tbm_queue,
                                                                                                wl_egl_buffer->tbm_surface);
@@ -2549,8 +2553,8 @@ __thread_func_waiting_source_dispatch(tpl_gsource *gsource, uint64_t message)
                          wl_egl_buffer, tbm_surface);
 
        tpl_gmutex_lock(&wl_egl_buffer->mutex);
-       tpl_gcond_signal(&wl_egl_buffer->cond);
        wl_egl_buffer->status = WAITING_VBLANK;
+       tpl_gcond_signal(&wl_egl_buffer->cond);
        tpl_gmutex_unlock(&wl_egl_buffer->mutex);
 
        tpl_gmutex_lock(&wl_egl_surface->surf_mutex);