e_comp_wl_data: Support 64k over size data transfer 63/300763/1
authorJunkyeong Kim <jk0430.kim@samsung.com>
Mon, 30 Oct 2023 09:58:12 +0000 (18:58 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Thu, 2 Nov 2023 02:17:18 +0000 (11:17 +0900)
Use ecore_thread_run to support pipe capacity(64k) exceed data transferring.

Change-Id: I37bfc681cd77cbf3bd41e6d1a3ee42085bbc2118

src/bin/e_comp_wl_data.c
src/bin/e_comp_wl_data.h

index f2a2cff..3fcb2d3 100644 (file)
@@ -1,6 +1,11 @@
 #define EXECUTIVE_MODE_ENABLED
 #include "e.h"
 
+typedef struct {
+   int src_fd;
+   int dst_fd;
+} E_Comp_Wl_Thread_Data;
+
 static void _e_comp_wl_data_source_cancelled_send(E_Comp_Wl_Data_Source *source);
 
 static void
@@ -28,12 +33,126 @@ _e_comp_wl_data_offer_cb_accept(struct wl_client *client EINA_UNUSED, struct wl_
      }
 }
 
+static void
+_e_comp_wl_data_pipe_run(void *data, Ecore_Thread *th)
+{
+   E_Comp_Wl_Thread_Data *td;
+   char *p = NULL;
+   int read_len = 0, write_len = 0;
+   int retry_position, retry_cnt = 0;
+
+   if (!(td = data)) return;
+
+   eina_thread_name_set(eina_thread_self(), "e_comp_wl_data_pipe");
+
+   if (ecore_thread_check(th)) return;
+
+   DBG("_e_comp_wl_data_pipe_run. th:%p", th);
+
+   p = (char *)calloc(sizeof(char), CLIPBOARD_CHUNK);
+   if (!p) return;
+
+   while (1)
+     {
+        read_len = read(td->src_fd, p, CLIPBOARD_CHUNK);
+        if (read_len == -1)
+          {
+             if (errno == EINTR || errno == EAGAIN)
+               {
+                  DBG("IO error in _e_comp_wl_dnd_offer_mediate READ. try again");
+                  retry_cnt++;
+                  if (retry_cnt > 10000)
+                    {
+                       ERR("retry over 10000. break");
+                       goto cleanup;
+                    }
+                  continue;
+               }
+             else
+               {
+                  DBG("IO error in _e_comp_wl_dnd_offer_mediate READ.(%d)", errno);
+                  goto cleanup;
+               }
+          }
+
+        retry_position = 0;
+        while (1)
+          {
+             write_len = write(td->dst_fd, p + retry_position, read_len - retry_position);
+             if (write_len == -1)
+               {
+                  if (errno == EINTR || errno == EAGAIN)
+                    {
+                       DBG("IO error in _e_comp_wl_dnd_offer_mediate WRITE. try again");
+                       continue;
+                    }
+                  else
+                    {
+                       ERR("IO error in _e_comp_wl_dnd_offer_mediate WRITE.(%d)", errno);
+                       goto cleanup;
+                    }
+               }
+             else if (read_len - retry_position == write_len)
+               {
+                  break;
+               }
+             else
+               {
+                  retry_position = read_len - write_len;
+                  continue;
+               }
+          }
+
+        if ((char *)(p[read_len - 1] == '\0'))
+          {
+             DBG("mediate done. read and write done");
+             break;
+          }
+        retry_cnt = 0;
+     }
+
+cleanup:
+      if (p) free(p);
+}
+
+static void
+_e_comp_wl_data_pipe_close(E_Comp_Wl_Thread_Data *td)
+{
+   close(td->src_fd);
+   close(td->dst_fd);
+
+   E_FREE(td);
+}
+
+static void
+_e_comp_wl_data_pipe_done(void *data, Ecore_Thread *th)
+{
+   E_Comp_Wl_Thread_Data *td = data;
+
+   if (!td) return;
+
+   DBG("_e_comp_wl_data_pipe_done. th:%p", th);
+
+   _e_comp_wl_data_pipe_close(td);
+}
+
+static void
+_e_comp_wl_data_pipe_cancel(void *data, Ecore_Thread *th)
+{
+   E_Comp_Wl_Thread_Data *td = data;
+
+   if (!td) return;
+
+   DBG("_e_comp_wl_data_pipe_cancel. th:%p", th);
+
+   _e_comp_wl_data_pipe_close(td);
+}
+
 static Eina_Bool
 _e_comp_wl_dnd_offer_mediate(void *data, Ecore_Fd_Handler *handler)
 {
    E_Comp_Wl_Data_Offer *offer = NULL;
-   char *p = NULL;
-   int read_len = 0, write_len = 0;
+   E_Comp_Wl_Thread_Data *td;
    int source_fd = -1;
 
    if (!(offer = (E_Comp_Wl_Data_Offer*)data))
@@ -43,18 +162,23 @@ _e_comp_wl_dnd_offer_mediate(void *data, Ecore_Fd_Handler *handler)
    if (source_fd < 0) goto cleanup;
    if (offer->fd < 0) goto cleanup;
 
-   p = (char *)calloc(sizeof(char), CLIPBOARD_CHUNK);
-   if (!p) goto cleanup;
+   td = E_NEW(E_Comp_Wl_Thread_Data, 1);
+   if (!td) return ECORE_CALLBACK_RENEW;
 
-   while ((read_len = read(source_fd, p, CLIPBOARD_CHUNK)) > 0)
-     {
-        write_len = write(offer->fd, p, read_len);
-        if (read_len != write_len)
-        {
-           ERR("IO error in _e_comp_wl_dnd_offer_mediate");
-           break;
-        }
-     }
+   td->src_fd = source_fd;
+   td->dst_fd = offer->fd;
+   offer->th = ecore_thread_run(_e_comp_wl_data_pipe_run,
+                                _e_comp_wl_data_pipe_done,
+                                _e_comp_wl_data_pipe_cancel,
+                                td);
+   if (offer->th == NULL)
+     goto cleanup;
+
+   ecore_main_fd_handler_del(handler);
+
+   DBG("create thread for pipe th:%p,  src:%d, dst:%d", offer->th, td->src_fd, td->dst_fd);
+
+   return ECORE_CALLBACK_DONE;
 
 cleanup:
    if (offer->fd > 0)
@@ -63,8 +187,7 @@ cleanup:
         offer->fd = 0;
      }
    if (source_fd > 0) close(source_fd);
-   if (handler != NULL) ecore_main_fd_handler_del(handler);
-   if (p) free(p);
+   ecore_main_fd_handler_del(handler);
 
    return ECORE_CALLBACK_DONE;
 }
@@ -76,10 +199,10 @@ _e_comp_wl_dnd_offer_mediator_init(E_Comp_Wl_Data_Offer* offer, int fd)
    EINA_SAFETY_ON_NULL_RETURN_VAL(offer->source, -1);
 
    if (pipe2(offer->source->fd, O_CLOEXEC|O_DIRECT|O_NONBLOCK) == -1)
-   {
-      ERR("Could not create unidirectional pipe for dnd: %m");
-      return -1;
-   }
+     {
+        ERR("Could not create unidirectional pipe for dnd: %m");
+        return -1;
+     }
 
    offer->fd = fd;
    offer->source->fd_handler =
@@ -237,6 +360,12 @@ _e_comp_wl_data_offer_cb_resource_destroy(struct wl_resource *resource)
    if (offer == e_comp_wl->drag_offer)
      e_comp_wl->drag_offer = NULL;
 
+   if ((offer->th != NULL) && !ecore_thread_check(offer->th))
+     {
+        ecore_thread_cancel(offer->th);
+        offer->th = NULL;
+     }
+
    free(offer);
 }
 
index aec93bc..c73671a 100644 (file)
@@ -54,6 +54,8 @@ struct _E_Comp_Wl_Data_Offer
    uint32_t dnd_actions;
    enum wl_data_device_manager_dnd_action preferred_dnd_action;
    Eina_Bool in_ask;
+
+   Ecore_Thread *th;
 };
 
 struct _E_Comp_Wl_Clipboard_Source