2018-02-27 04:19:17 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define EFL_IO_READER_PROTECTED 1
|
|
|
|
#define EFL_IO_WRITER_PROTECTED 1
|
|
|
|
#define EFL_IO_CLOSER_PROTECTED 1
|
|
|
|
|
|
|
|
#include <Ecore.h>
|
|
|
|
|
|
|
|
#include "ecore_private.h"
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#define MY_CLASS EFL_THREAD_CLASS
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
#define APPTHREAD_CLASS EFL_APPTHREAD_CLASS
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
struct {
|
|
|
|
int in, out;
|
|
|
|
Eo *in_handler, *out_handler;
|
|
|
|
} fd, ctrl;
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
Eina_Array *argv;
|
2018-02-27 04:19:17 -08:00
|
|
|
Efl_Callback_Array_Item_Full *event_cb;
|
2018-03-06 03:49:51 -08:00
|
|
|
void *indata, *outdata;
|
2018-02-27 04:19:17 -08:00
|
|
|
} Thread_Data;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
#define CMD_EXIT 1
|
|
|
|
#define CMD_EXITED 2
|
|
|
|
#define CMD_CALL 3
|
|
|
|
#define CMD_CALL_SYNC 4
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2018-03-06 03:49:51 -08:00
|
|
|
Eina_Semaphore sem;
|
|
|
|
void *data;
|
|
|
|
} Control_Reply;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
int command;
|
|
|
|
int data;
|
|
|
|
void *ptr[4];
|
|
|
|
} d;
|
|
|
|
unsigned char b[64];
|
|
|
|
};
|
2018-02-27 04:19:17 -08:00
|
|
|
} Control_Data;
|
|
|
|
|
|
|
|
typedef struct _Efl_Thread_Data Efl_Thread_Data;
|
|
|
|
|
|
|
|
struct _Efl_Thread_Data
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
int in, out;
|
|
|
|
Eo *in_handler, *out_handler;
|
|
|
|
Eina_Bool can_read : 1;
|
|
|
|
Eina_Bool eos_read : 1;
|
|
|
|
Eina_Bool can_write : 1;
|
|
|
|
} fd, ctrl;
|
|
|
|
int read_listeners;
|
2018-03-20 04:43:47 -07:00
|
|
|
Eina_Promise *promise;
|
2018-02-27 04:19:17 -08:00
|
|
|
Eo *loop;
|
|
|
|
Thread_Data *thdat;
|
|
|
|
Efl_Callback_Array_Item_Full *event_cb;
|
|
|
|
Eina_Thread thread;
|
|
|
|
Eina_Bool end_sent : 1;
|
|
|
|
Eina_Bool exit_read : 1;
|
|
|
|
Eina_Bool exit_called : 1;
|
2018-03-10 03:02:09 -08:00
|
|
|
Eina_Bool run : 1;
|
2018-02-27 04:19:17 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_in(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
Control_Data cmd;
|
|
|
|
ssize_t ret;
|
|
|
|
Efl_Appthread_Data *ad;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
ad = efl_data_scope_get(obj, APPTHREAD_CLASS);
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
2018-02-27 04:19:17 -08:00
|
|
|
ret = read(ad->ctrl.out, &cmd, sizeof(Control_Data));
|
|
|
|
if (ret == sizeof(Control_Data))
|
|
|
|
{
|
2018-03-06 03:49:51 -08:00
|
|
|
if (cmd.d.command == CMD_EXIT)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
2018-03-20 04:43:47 -07:00
|
|
|
efl_event_callback_call(obj, EFL_LOOP_EVENT_QUIT, NULL);
|
2018-02-27 04:19:17 -08:00
|
|
|
efl_loop_quit(obj, eina_value_int_init(0));
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
else if (cmd.d.command == CMD_CALL)
|
|
|
|
{
|
|
|
|
EFlThreadIOCall func = cmd.d.ptr[0];
|
|
|
|
void *data = cmd.d.ptr[1];
|
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
|
|
|
Efl_Event event = { obj, NULL, NULL };
|
|
|
|
|
|
|
|
func(data, &event);
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
if (free_func) free_func(data);
|
|
|
|
}
|
|
|
|
else if (cmd.d.command == CMD_CALL_SYNC)
|
|
|
|
{
|
|
|
|
EFlThreadIOCallSync func = cmd.d.ptr[0];
|
|
|
|
void *data = cmd.d.ptr[1];
|
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
|
|
|
Control_Reply *rep = cmd.d.ptr[3];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
|
|
|
Efl_Event event = { obj, NULL, NULL };
|
|
|
|
|
|
|
|
rep->data = func(data, &event);
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
if (free_func) free_func(data);
|
|
|
|
eina_semaphore_release(&(rep->sem), 1);
|
|
|
|
}
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Value
|
2018-12-07 03:29:22 -08:00
|
|
|
_efl_loop_arguments_send(Eo *obj, void *data EINA_UNUSED, const Eina_Value v)
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
{
|
|
|
|
Efl_Loop_Arguments arge;
|
|
|
|
Eina_Array *arga;
|
|
|
|
Eina_Stringshare *s;
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
Eina_Accessor *accessor;
|
|
|
|
const char *argv;
|
|
|
|
int i = 0;
|
2018-02-27 04:19:17 -08:00
|
|
|
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
accessor = efl_core_command_line_command_access(obj);
|
|
|
|
arga = eina_array_new(10);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
EINA_ACCESSOR_FOREACH(accessor, i, argv)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
eina_array_push(arga, eina_stringshare_add(argv));
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
arge.argv = arga;
|
|
|
|
arge.initialization = EINA_TRUE;
|
|
|
|
efl_event_callback_call(obj,
|
|
|
|
EFL_LOOP_EVENT_ARGUMENTS, &arge);
|
2018-12-07 03:29:22 -08:00
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
while ((s = eina_array_pop(arga))) eina_stringshare_del(s);
|
|
|
|
eina_array_free(arga);
|
2018-12-07 03:29:22 -08:00
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_appthread_parent_read_listeners_modify(Efl_Appthread_Data *ad, int mod)
|
|
|
|
{
|
|
|
|
ad->read_listeners += mod;
|
|
|
|
|
|
|
|
if (ad->fd.out_handler)
|
|
|
|
{
|
|
|
|
if ((ad->read_listeners == 0) && (mod < 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
|
|
|
|
else if ((ad->read_listeners == 1) && (mod > 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_appthread_event_callback_add(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Appthread_Data *ad = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_appthread_parent_read_listeners_modify(ad, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_appthread_event_callback_del(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Appthread_Data *ad = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_appthread_parent_read_listeners_modify(ad, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_appthread_event_callback_watch,
|
|
|
|
{ EFL_EVENT_CALLBACK_ADD, _cb_appthread_event_callback_add },
|
|
|
|
{ EFL_EVENT_CALLBACK_DEL, _cb_appthread_event_callback_del });
|
|
|
|
|
|
|
|
static void *
|
|
|
|
_efl_thread_main(void *data, Eina_Thread t)
|
|
|
|
{
|
|
|
|
Efl_Appthread_Data *ad;
|
|
|
|
Thread_Data *thdat = data;
|
|
|
|
Eo *obj;
|
|
|
|
Eina_Value *ret;
|
|
|
|
Control_Data cmd;
|
|
|
|
int real;
|
|
|
|
Efl_Callback_Array_Item_Full *it;
|
|
|
|
|
|
|
|
if (thdat->name) eina_thread_name_set(t, thdat->name);
|
|
|
|
else eina_thread_name_set(t, "Eflthread");
|
|
|
|
|
2018-03-15 09:50:20 -07:00
|
|
|
obj = efl_add_ref(APPTHREAD_CLASS, NULL);
|
2018-03-06 03:49:51 -08:00
|
|
|
ad = efl_data_scope_get(obj, APPTHREAD_CLASS);
|
|
|
|
efl_threadio_indata_set(obj, thdat->indata);
|
|
|
|
efl_threadio_outdata_set(obj, thdat->outdata);
|
2018-02-27 04:19:17 -08:00
|
|
|
efl_event_callback_array_add(obj, _appthread_event_callback_watch(), ad);
|
|
|
|
|
|
|
|
// add handlers for "stdio"
|
|
|
|
thdat->fd.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->fd.in),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_in, obj));
|
|
|
|
thdat->fd.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->fd.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_out, obj));
|
|
|
|
// add handlers for control pipes
|
|
|
|
thdat->ctrl.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->ctrl.in));
|
|
|
|
thdat->ctrl.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->ctrl.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_ctrl_out, obj),
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
|
|
|
|
ad->fd.in = thdat->fd.in;
|
|
|
|
ad->fd.out = thdat->fd.out;
|
|
|
|
ad->ctrl.in = thdat->ctrl.in;
|
|
|
|
ad->ctrl.out = thdat->ctrl.out;
|
|
|
|
ad->fd.in_handler = thdat->fd.in_handler;
|
|
|
|
ad->fd.out_handler = thdat->fd.out_handler;
|
|
|
|
ad->ctrl.in_handler = thdat->ctrl.in_handler;
|
|
|
|
ad->ctrl.out_handler = thdat->ctrl.out_handler;
|
2018-03-06 03:49:51 -08:00
|
|
|
ad->thdat = thdat;
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
if (thdat->event_cb)
|
|
|
|
{
|
|
|
|
for (it = thdat->event_cb; it->func; it++)
|
|
|
|
efl_event_callback_priority_add(obj, it->desc, it->priority,
|
|
|
|
it->func, it->user_data);
|
|
|
|
}
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
efl_core_command_line_command_array_set(obj, thdat->argv);
|
2018-12-07 03:29:22 -08:00
|
|
|
efl_future_then(obj, efl_loop_job(obj),
|
|
|
|
.success = _efl_loop_arguments_send);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
while (thdat->argv && eina_array_count(thdat->argv)) free(eina_array_pop(thdat->argv));
|
|
|
|
eina_array_free(thdat->argv);
|
2018-02-27 04:19:17 -08:00
|
|
|
free(thdat->event_cb);
|
|
|
|
thdat->event_cb = NULL;
|
|
|
|
|
|
|
|
ret = efl_loop_begin(obj);
|
|
|
|
real = efl_loop_exit_code_process(ret);
|
2018-03-06 03:49:51 -08:00
|
|
|
thdat->outdata = efl_threadio_outdata_get(obj);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_EXITED;
|
|
|
|
cmd.d.data = real;
|
2018-02-27 04:19:17 -08:00
|
|
|
write(thdat->ctrl.in, &cmd, sizeof(Control_Data));
|
|
|
|
|
2018-03-15 09:50:20 -07:00
|
|
|
efl_unref(obj);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
thdat->fd.in_handler = NULL;
|
|
|
|
thdat->fd.out_handler = NULL;
|
|
|
|
thdat->ctrl.in_handler = NULL;
|
|
|
|
thdat->ctrl.out_handler = NULL;
|
|
|
|
thdat->fd.in = -1;
|
|
|
|
thdat->fd.out = -1;
|
|
|
|
thdat->ctrl.in = -1;
|
|
|
|
thdat->ctrl.out = -1;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static void
|
|
|
|
_thread_exit_eval(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
if ((pd->fd.out == -1) && /*(pd->fd.in == -1) &&*/
|
|
|
|
(pd->exit_read) && (!pd->exit_called))
|
|
|
|
{
|
|
|
|
pd->exit_called = EINA_TRUE;
|
2018-03-06 03:49:51 -08:00
|
|
|
if (pd->thdat) efl_threadio_outdata_set(obj, pd->thdat->outdata);
|
2018-03-20 04:43:47 -07:00
|
|
|
if (pd->promise)
|
|
|
|
{
|
2018-03-26 04:53:06 -07:00
|
|
|
Eina_Promise *p = pd->promise;
|
2018-03-20 04:43:47 -07:00
|
|
|
int exit_code = efl_task_exit_code_get(obj);
|
2018-04-03 10:34:10 -07:00
|
|
|
if ((exit_code != 0) && (!(efl_task_flags_get(obj) &
|
|
|
|
EFL_TASK_FLAGS_NO_EXIT_CODE_ERROR)))
|
|
|
|
eina_promise_reject(p, exit_code + 1000000);
|
|
|
|
else eina_promise_resolve(p, eina_value_int_init(exit_code));
|
2018-03-20 04:43:47 -07:00
|
|
|
}
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_parent_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_parent_in(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_parent_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
Control_Data cmd;
|
|
|
|
ssize_t ret;
|
|
|
|
Efl_Thread_Data *pd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
|
|
|
|
if (!pd) return;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
2018-02-27 04:19:17 -08:00
|
|
|
ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
|
|
|
|
if (ret == sizeof(Control_Data))
|
|
|
|
{
|
2018-03-06 03:49:51 -08:00
|
|
|
if (cmd.d.command == CMD_EXITED)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
if (!pd->exit_read)
|
|
|
|
{
|
|
|
|
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
if (td) td->exit_code = cmd.d.data;
|
2018-02-27 04:19:17 -08:00
|
|
|
pd->exit_read = EINA_TRUE;
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
}
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
else if (cmd.d.command == CMD_CALL)
|
|
|
|
{
|
|
|
|
EFlThreadIOCall func = cmd.d.ptr[0];
|
|
|
|
void *data = cmd.d.ptr[1];
|
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
|
|
|
Efl_Event event = { obj, NULL, NULL };
|
|
|
|
|
|
|
|
func(data, &event);
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
if (free_func) free_func(data);
|
|
|
|
}
|
|
|
|
else if (cmd.d.command == CMD_CALL_SYNC)
|
|
|
|
{
|
|
|
|
EFlThreadIOCallSync func = cmd.d.ptr[0];
|
|
|
|
void *data = cmd.d.ptr[1];
|
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
|
|
|
Control_Reply *rep = cmd.d.ptr[3];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
|
|
|
Efl_Event event = { obj, NULL, NULL };
|
|
|
|
|
|
|
|
rep->data = func(data, &event);
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
if (free_func) free_func(data);
|
|
|
|
eina_semaphore_release(&(rep->sem), 1);
|
|
|
|
}
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2019-01-04 17:42:26 -08:00
|
|
|
static Eina_Value
|
|
|
|
_run_cancel_cb(Efl_Loop_Consumer *consumer, void *data EINA_UNUSED, Eina_Error error)
|
|
|
|
{
|
|
|
|
if (error == ECANCELED) efl_task_end(consumer);
|
|
|
|
|
|
|
|
return eina_value_error_init(error);
|
|
|
|
}
|
|
|
|
|
2018-03-20 04:43:47 -07:00
|
|
|
static void
|
2019-01-04 17:42:26 -08:00
|
|
|
_run_clean_cb(Efl_Loop_Consumer *consumer EINA_UNUSED,void *data, const Eina_Future *dead_future EINA_UNUSED)
|
2018-03-20 04:43:47 -07:00
|
|
|
{
|
2019-01-04 17:42:26 -08:00
|
|
|
Efl_Thread_Data *pd = data;
|
|
|
|
|
2018-03-20 04:43:47 -07:00
|
|
|
pd->promise = NULL;
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
static void
|
|
|
|
_thread_parent_read_listeners_modify(Efl_Thread_Data *pd, int mod)
|
|
|
|
{
|
|
|
|
pd->read_listeners += mod;
|
|
|
|
|
|
|
|
if (pd->fd.out_handler)
|
|
|
|
{
|
|
|
|
if ((pd->read_listeners == 0) && (mod < 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
|
|
|
|
else if ((pd->read_listeners == 1) && (mod > 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_event_callback_add(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Thread_Data *pd = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
|
|
|
|
{
|
|
|
|
Efl_Callback_Array_Item_Full *event_cb, *it;
|
|
|
|
int num;
|
|
|
|
|
|
|
|
num = 0;
|
|
|
|
if (pd->event_cb)
|
|
|
|
{
|
|
|
|
for (it = pd->event_cb; it->func; it++) num++;
|
|
|
|
}
|
|
|
|
num++;
|
|
|
|
event_cb = realloc(pd->event_cb, (num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
|
|
|
if (event_cb)
|
|
|
|
{
|
|
|
|
pd->event_cb = event_cb;
|
|
|
|
event_cb[num - 1] = array[i];
|
|
|
|
event_cb[num].desc = NULL;
|
|
|
|
event_cb[num].priority = 0;
|
|
|
|
event_cb[num].func = NULL;
|
|
|
|
event_cb[num].user_data = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_thread_parent_read_listeners_modify(pd, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_event_callback_del(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Thread_Data *pd = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
|
|
|
|
{
|
|
|
|
Efl_Callback_Array_Item_Full *it;
|
|
|
|
|
|
|
|
if (pd->event_cb)
|
|
|
|
{
|
|
|
|
Eina_Bool shuffle_down = EINA_FALSE;
|
|
|
|
|
|
|
|
for (it = pd->event_cb; it->func; it++)
|
|
|
|
{
|
|
|
|
if ((it->desc == array[i].desc) &&
|
|
|
|
(it->priority == array[i].priority) &&
|
|
|
|
(it->func == array[i].func) &&
|
|
|
|
(it->user_data == array[i].user_data))
|
|
|
|
shuffle_down = EINA_TRUE;
|
|
|
|
if (shuffle_down) it[0] = it[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_thread_parent_read_listeners_modify(pd, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
|
|
|
|
{ EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
|
|
|
|
{ EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
EOLIAN static Efl_Object *
|
|
|
|
_efl_thread_efl_object_constructor(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
|
|
|
efl_event_callback_array_add(obj, _event_callback_watch(), pd);
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->fd.can_write = EINA_TRUE;
|
|
|
|
pd->ctrl.in = -1;
|
|
|
|
pd->ctrl.out = -1;
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_object_destructor(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
2018-03-26 04:53:06 -07:00
|
|
|
if (pd->promise)
|
|
|
|
ERR("Thread being destroyed while real worker has not exited yet.");
|
2018-02-27 04:19:17 -08:00
|
|
|
if (pd->thdat)
|
|
|
|
{
|
|
|
|
eina_thread_join(pd->thread);
|
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
efl_del(pd->ctrl.in_handler);
|
|
|
|
efl_del(pd->ctrl.out_handler);
|
|
|
|
close(pd->fd.in);
|
|
|
|
close(pd->fd.out);
|
|
|
|
close(pd->ctrl.in);
|
|
|
|
close(pd->ctrl.out);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
pd->ctrl.in_handler = NULL;
|
|
|
|
pd->ctrl.out_handler = NULL;
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->ctrl.in = -1;
|
|
|
|
pd->ctrl.out = -1;
|
|
|
|
free(pd->thdat);
|
|
|
|
}
|
|
|
|
free(pd->event_cb);
|
|
|
|
pd->event_cb = NULL;
|
|
|
|
efl_destructor(efl_super(obj, MY_CLASS));
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_object_parent_set(Eo *obj, Efl_Thread_Data *pd, Efl_Object *parent)
|
|
|
|
{
|
|
|
|
efl_parent_set(efl_super(obj, MY_CLASS), parent);
|
|
|
|
pd->loop = efl_provider_find(parent, EFL_LOOP_CLASS);
|
|
|
|
}
|
|
|
|
|
2018-03-20 04:43:47 -07:00
|
|
|
EOLIAN static Eina_Future *
|
2018-02-27 04:19:17 -08:00
|
|
|
_efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
Eina_Thread_Priority pri;
|
|
|
|
Thread_Data *thdat;
|
|
|
|
const char *name;
|
|
|
|
int pipe_to_thread[2];
|
|
|
|
int pipe_from_thread[2];
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
unsigned int num;
|
2018-02-27 04:19:17 -08:00
|
|
|
Efl_Callback_Array_Item_Full *it;
|
2018-03-06 01:31:48 -08:00
|
|
|
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
2018-03-20 04:43:47 -07:00
|
|
|
if (pd->run) return NULL;
|
|
|
|
if (!td) return NULL;
|
2018-02-27 04:19:17 -08:00
|
|
|
thdat = calloc(1, sizeof(Thread_Data));
|
2018-03-20 04:43:47 -07:00
|
|
|
if (!thdat) return NULL;
|
2018-02-27 04:19:17 -08:00
|
|
|
thdat->fd.in = -1;
|
|
|
|
thdat->fd.out = -1;
|
|
|
|
thdat->ctrl.in = -1;
|
|
|
|
thdat->ctrl.out = -1;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
thdat->indata = efl_threadio_indata_get(obj);
|
|
|
|
thdat->outdata = efl_threadio_outdata_get(obj);
|
|
|
|
|
2018-03-06 01:31:48 -08:00
|
|
|
// input/output pipes
|
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDIN)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
2018-03-06 01:31:48 -08:00
|
|
|
if (pipe(pipe_to_thread) != 0)
|
|
|
|
{
|
|
|
|
ERR("Can't create to_thread pipe");
|
|
|
|
free(thdat);
|
2018-03-20 04:43:47 -07:00
|
|
|
return NULL;
|
2018-03-06 01:31:48 -08:00
|
|
|
}
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
2018-03-06 01:31:48 -08:00
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDOUT)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
2018-03-06 01:31:48 -08:00
|
|
|
if (pipe(pipe_from_thread) != 0)
|
|
|
|
{
|
|
|
|
ERR("Can't create from_thread pipe");
|
|
|
|
close(pipe_to_thread[0]);
|
|
|
|
close(pipe_to_thread[1]);
|
|
|
|
free(thdat);
|
2018-03-20 04:43:47 -07:00
|
|
|
return NULL;
|
2018-03-06 01:31:48 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDIN)
|
|
|
|
{
|
|
|
|
thdat->fd.in = pipe_from_thread[1]; // write - input to parent
|
|
|
|
pd->fd.out = pipe_from_thread[0]; // read - output from child
|
|
|
|
eina_file_close_on_exec(thdat->fd.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(pd->fd.out, EINA_TRUE);
|
2019-01-29 02:30:45 -08:00
|
|
|
if (fcntl(thdat->fd.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->fd.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
2018-03-06 01:31:48 -08:00
|
|
|
pd->fd.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->fd.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_out, obj));
|
|
|
|
if (pd->read_listeners > 0)
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
|
|
|
}
|
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDOUT)
|
|
|
|
{
|
|
|
|
pd->fd.in = pipe_to_thread [1]; // write - input to child
|
|
|
|
thdat->fd.out = pipe_to_thread [0]; // read - output from parent
|
|
|
|
eina_file_close_on_exec(pd->fd.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(thdat->fd.out, EINA_TRUE);
|
2019-01-29 02:30:45 -08:00
|
|
|
if (fcntl(thdat->fd.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->fd.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
2018-03-06 01:31:48 -08:00
|
|
|
pd->fd.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->fd.in),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_parent_in, obj));
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
|
2018-03-06 01:31:48 -08:00
|
|
|
// control pipes
|
2018-02-27 04:19:17 -08:00
|
|
|
if (pipe(pipe_to_thread) != 0)
|
|
|
|
{
|
|
|
|
ERR("Can't create to_thread control pipe");
|
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
close(thdat->fd.in);
|
|
|
|
close(thdat->fd.out);
|
|
|
|
close(pd->fd.in);
|
|
|
|
close(pd->fd.out);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
free(thdat);
|
2018-03-20 04:43:47 -07:00
|
|
|
return NULL;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
if (pipe(pipe_from_thread) != 0)
|
|
|
|
{
|
|
|
|
ERR("Can't create from_thread control pipe");
|
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
close(pipe_to_thread[0]);
|
|
|
|
close(pipe_to_thread[1]);
|
|
|
|
close(thdat->fd.in);
|
|
|
|
close(thdat->fd.out);
|
|
|
|
close(pd->fd.in);
|
|
|
|
close(pd->fd.out);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
free(thdat);
|
2018-03-20 04:43:47 -07:00
|
|
|
return NULL;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
thdat->ctrl.in = pipe_from_thread[1]; // write - input to parent
|
|
|
|
thdat->ctrl.out = pipe_to_thread [0]; // read - output from parent
|
|
|
|
pd->ctrl.in = pipe_to_thread [1]; // write - input to child
|
|
|
|
pd->ctrl.out = pipe_from_thread[0]; // read - output from child
|
2019-01-29 02:30:45 -08:00
|
|
|
if (fcntl(thdat->ctrl.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(thdat->ctrl.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->ctrl.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->ctrl.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
2018-02-27 04:19:17 -08:00
|
|
|
eina_file_close_on_exec(pd->ctrl.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(pd->ctrl.out, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(thdat->ctrl.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(thdat->ctrl.out, EINA_TRUE);
|
|
|
|
pd->ctrl.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->ctrl.in));
|
|
|
|
pd->ctrl.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->ctrl.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_ctrl_out, obj),
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
|
|
|
|
|
|
|
|
switch (efl_task_priority_get(obj))
|
|
|
|
{
|
|
|
|
case EFL_TASK_PRIORITY_BACKGROUND:
|
|
|
|
pri = EINA_THREAD_IDLE;
|
|
|
|
break;
|
|
|
|
case EFL_TASK_PRIORITY_HIGH:
|
|
|
|
case EFL_TASK_PRIORITY_ULTRA:
|
|
|
|
pri = EINA_THREAD_URGENT;
|
|
|
|
break;
|
|
|
|
case EFL_TASK_PRIORITY_LOW:
|
|
|
|
pri = EINA_THREAD_BACKGROUND;
|
|
|
|
break;
|
|
|
|
case EFL_TASK_PRIORITY_NORMAL:
|
|
|
|
default:
|
|
|
|
pri = EINA_THREAD_NORMAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
name = efl_name_get(obj);
|
|
|
|
if (name) thdat->name = eina_stringshare_add(name);
|
|
|
|
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
{
|
|
|
|
Eina_Accessor *acc;
|
|
|
|
int i = 0;
|
|
|
|
const char *argv;
|
|
|
|
|
|
|
|
acc = efl_core_command_line_command_access(obj);
|
|
|
|
if (acc)
|
|
|
|
{
|
|
|
|
thdat->argv = eina_array_new(0);
|
|
|
|
EINA_ACCESSOR_FOREACH(acc, i, argv)
|
|
|
|
{
|
|
|
|
eina_array_push(thdat->argv, eina_stringshare_add(argv));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
if (pd->event_cb)
|
|
|
|
{
|
|
|
|
num = 0;
|
|
|
|
for (it = pd->event_cb; it->func; it++) num++;
|
|
|
|
thdat->event_cb = malloc((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
|
|
|
if (thdat->event_cb)
|
|
|
|
memcpy(thdat->event_cb, pd->event_cb,
|
|
|
|
(num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
|
|
|
// XXX: if malloc fails?
|
|
|
|
}
|
|
|
|
|
|
|
|
// env data - ignore as other end will share same env
|
|
|
|
|
|
|
|
if (!eina_thread_create(&(pd->thread), pri, -1, _efl_thread_main, thdat))
|
|
|
|
{
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
while (eina_array_count(thdat->argv)) eina_stringshare_del(eina_array_pop(thdat->argv));
|
|
|
|
eina_array_free(thdat->argv);
|
2018-02-27 04:19:17 -08:00
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
efl_del(pd->ctrl.in_handler);
|
|
|
|
efl_del(pd->ctrl.out_handler);
|
|
|
|
close(pd->fd.in);
|
|
|
|
close(pd->fd.out);
|
|
|
|
close(pd->ctrl.in);
|
|
|
|
close(pd->ctrl.out);
|
|
|
|
close(thdat->fd.in);
|
|
|
|
close(thdat->fd.out);
|
|
|
|
close(thdat->ctrl.in);
|
|
|
|
close(thdat->ctrl.out);
|
|
|
|
free(thdat);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
pd->ctrl.in_handler = NULL;
|
|
|
|
pd->ctrl.out_handler = NULL;
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->ctrl.in = -1;
|
|
|
|
pd->ctrl.out = -1;
|
2018-03-20 04:43:47 -07:00
|
|
|
return NULL;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
pd->thdat = thdat;
|
2018-03-10 03:02:09 -08:00
|
|
|
pd->run = EINA_TRUE;
|
2019-01-04 17:42:26 -08:00
|
|
|
pd->promise = efl_loop_promise_new(obj);
|
|
|
|
return efl_future_then(obj, eina_future_new(pd->promise),
|
|
|
|
.data = pd, .error = _run_cancel_cb, .free = _run_clean_cb);
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_task_end(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
if (pd->end_sent) return;
|
|
|
|
if (pd->thdat)
|
|
|
|
{
|
|
|
|
Control_Data cmd;
|
|
|
|
|
|
|
|
pd->end_sent = EINA_TRUE;
|
2018-03-06 03:49:51 -08:00
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_EXIT;
|
2018-02-27 04:19:17 -08:00
|
|
|
write(pd->ctrl.in, &cmd, sizeof(Control_Data));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_thread_efl_io_closer_close(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
if (!pd->thdat) return 0;
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
|
|
|
efl_io_reader_eos_set(obj, EINA_TRUE);
|
|
|
|
if (pd->fd.in >= 0) close(pd->fd.in);
|
|
|
|
if (pd->fd.out >= 0) close(pd->fd.out);
|
|
|
|
if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
|
|
|
|
if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_closer_closed_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_thread_efl_io_reader_read(Eo *obj, Efl_Thread_Data *pd, Eina_Rw_Slice *rw_slice)
|
|
|
|
{
|
|
|
|
ssize_t r;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
if (pd->fd.out == -1) goto err;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
errno = 0;
|
|
|
|
r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
|
|
|
|
if (r == -1)
|
|
|
|
{
|
|
|
|
if (errno == EINTR) continue;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (r == -1);
|
|
|
|
|
|
|
|
rw_slice->len = r;
|
|
|
|
if (r == 0)
|
|
|
|
{
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
|
|
|
efl_io_reader_eos_set(obj, EINA_TRUE);
|
|
|
|
close(pd->fd.out);
|
|
|
|
pd->fd.out = -1;
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EPIPE;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if ((pd->fd.out != -1) && (errno != EAGAIN))
|
|
|
|
{
|
|
|
|
close(pd->fd.out);
|
|
|
|
pd->fd.out = -1;
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
}
|
|
|
|
rw_slice->len = 0;
|
|
|
|
rw_slice->mem = NULL;
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_io_reader_can_read_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_read)
|
|
|
|
{
|
|
|
|
Eina_Bool old = efl_io_reader_can_read_get(obj);
|
|
|
|
if (old == can_read) return;
|
|
|
|
pd->fd.can_read = can_read;
|
|
|
|
if (!pd->fd.out_handler) return;
|
|
|
|
if (can_read)
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
|
|
|
else
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler,
|
|
|
|
EFL_LOOP_HANDLER_FLAGS_READ);
|
|
|
|
efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_reader_can_read_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
return pd->fd.can_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_io_reader_eos_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool is_eos)
|
|
|
|
{
|
|
|
|
Eina_Bool old = efl_io_reader_eos_get(obj);
|
|
|
|
if (old == is_eos) return;
|
|
|
|
|
|
|
|
pd->fd.eos_read = is_eos;
|
|
|
|
if (!is_eos) return;
|
|
|
|
if (pd->fd.out_handler)
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
|
|
|
efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_reader_eos_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
return pd->fd.eos_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_thread_efl_io_writer_write(Eo *obj, Efl_Thread_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
|
|
|
|
{
|
|
|
|
ssize_t r;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
if (pd->fd.in == -1) goto err;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
errno = 0;
|
|
|
|
r = write(pd->fd.in, slice->mem, slice->len);
|
|
|
|
if (r == -1)
|
|
|
|
{
|
|
|
|
if (errno == EINTR) continue;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (r == -1);
|
|
|
|
|
|
|
|
if (remaining)
|
|
|
|
{
|
|
|
|
remaining->len = slice->len - r;
|
|
|
|
remaining->bytes = slice->bytes + r;
|
|
|
|
}
|
|
|
|
slice->len = r;
|
|
|
|
|
|
|
|
if ((slice) && (slice->len > 0))
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
|
|
|
if (r == 0)
|
|
|
|
{
|
|
|
|
close(pd->fd.in);
|
|
|
|
pd->fd.in = -1;
|
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EPIPE;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if ((pd->fd.in != -1) && (errno != EAGAIN))
|
|
|
|
{
|
|
|
|
close(pd->fd.in);
|
|
|
|
pd->fd.in = -1;
|
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
}
|
|
|
|
if (remaining) *remaining = *slice;
|
|
|
|
slice->len = 0;
|
|
|
|
slice->mem = NULL;
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_io_writer_can_write_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_write)
|
|
|
|
{
|
|
|
|
Eina_Bool old = efl_io_writer_can_write_get(obj);
|
|
|
|
if (old == can_write) return;
|
|
|
|
pd->fd.can_write = can_write;
|
|
|
|
if (can_write)
|
|
|
|
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
|
|
|
else
|
|
|
|
efl_loop_handler_active_set(pd->fd.in_handler,
|
|
|
|
EFL_LOOP_HANDLER_FLAGS_WRITE);
|
|
|
|
efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_writer_can_write_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
return pd->fd.can_write;
|
|
|
|
}
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
void
|
|
|
|
_appthread_threadio_call(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd,
|
|
|
|
void *func_data, EFlThreadIOCall func, Eina_Free_Cb func_free_cb)
|
|
|
|
{
|
|
|
|
Thread_Data *thdat = pd->thdat;
|
|
|
|
Control_Data cmd;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_CALL;
|
|
|
|
cmd.d.ptr[0] = func;
|
|
|
|
cmd.d.ptr[1] = func_data;
|
|
|
|
cmd.d.ptr[2] = func_free_cb;
|
|
|
|
write(thdat->ctrl.in, &cmd, sizeof(Control_Data));
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_threadio_call(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd,
|
|
|
|
void *func_data, EFlThreadIOCall func, Eina_Free_Cb func_free_cb)
|
|
|
|
{
|
|
|
|
Control_Data cmd;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_CALL;
|
|
|
|
cmd.d.ptr[0] = func;
|
|
|
|
cmd.d.ptr[1] = func_data;
|
|
|
|
cmd.d.ptr[2] = func_free_cb;
|
|
|
|
write(pd->ctrl.in, &cmd, sizeof(Control_Data));
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
_appthread_threadio_call_sync(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd,
|
|
|
|
void *func_data, EFlThreadIOCallSync func, Eina_Free_Cb func_free_cb)
|
|
|
|
{
|
|
|
|
Thread_Data *thdat = pd->thdat;
|
|
|
|
Control_Data cmd;
|
|
|
|
Control_Reply *rep;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_CALL_SYNC;
|
|
|
|
cmd.d.ptr[0] = func;
|
|
|
|
cmd.d.ptr[1] = func_data;
|
|
|
|
cmd.d.ptr[2] = func_free_cb;
|
|
|
|
rep = malloc(sizeof(Control_Reply));
|
|
|
|
if (!rep) return NULL;
|
|
|
|
cmd.d.ptr[3] = rep;
|
|
|
|
rep->data = NULL;
|
|
|
|
eina_semaphore_new(&(rep->sem), 0);
|
|
|
|
write(thdat->ctrl.in, &cmd, sizeof(Control_Data));
|
|
|
|
eina_semaphore_lock(&(rep->sem));
|
|
|
|
data = rep->data;
|
|
|
|
free(rep);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void *
|
|
|
|
_efl_thread_efl_threadio_call_sync(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd,
|
|
|
|
void *func_data, EFlThreadIOCallSync func, Eina_Free_Cb func_free_cb)
|
|
|
|
{
|
|
|
|
Control_Data cmd;
|
|
|
|
Control_Reply *rep;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_CALL_SYNC;
|
|
|
|
cmd.d.ptr[0] = func;
|
|
|
|
cmd.d.ptr[1] = func_data;
|
|
|
|
cmd.d.ptr[2] = func_free_cb;
|
|
|
|
rep = malloc(sizeof(Control_Reply));
|
|
|
|
if (!rep) return NULL;
|
|
|
|
cmd.d.ptr[3] = rep;
|
|
|
|
rep->data = NULL;
|
|
|
|
eina_semaphore_new(&(rep->sem), 0);
|
|
|
|
write(pd->ctrl.in, &cmd, sizeof(Control_Data));
|
|
|
|
eina_semaphore_lock(&(rep->sem));
|
|
|
|
data = rep->data;
|
|
|
|
free(rep);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "efl_thread.eo.c"
|