#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
}
}
+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))
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)
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;
}
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 =
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);
}