2011-11-20 08:48:02 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2018-01-02 21:23:10 -08:00
|
|
|
#include <unistd.h>
|
2012-10-16 01:57:18 -07:00
|
|
|
#include <errno.h>
|
2011-11-20 07:17:29 -08:00
|
|
|
|
2016-11-04 02:06:11 -07:00
|
|
|
#ifdef _WIN32
|
|
|
|
# include <winsock2.h>
|
2019-05-20 05:46:02 -07:00
|
|
|
# include <evil_private.h> /* fcntl */
|
|
|
|
#endif
|
2017-02-07 13:40:48 -08:00
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include "evas_common_private.h"
|
|
|
|
#include "evas_private.h"
|
|
|
|
#include "Ecore.h"
|
2016-11-04 02:06:11 -07:00
|
|
|
|
2008-04-30 05:21:31 -07:00
|
|
|
typedef struct _Evas_Event_Async Evas_Event_Async;
|
|
|
|
struct _Evas_Event_Async
|
|
|
|
{
|
2010-08-28 18:59:21 -07:00
|
|
|
const void *target;
|
|
|
|
void *event_info;
|
|
|
|
Evas_Async_Events_Put_Cb func;
|
|
|
|
Evas_Callback_Type type;
|
2009-02-12 09:05:17 -08:00
|
|
|
};
|
2008-04-30 05:21:31 -07:00
|
|
|
|
2013-05-29 23:42:56 -07:00
|
|
|
typedef struct _Evas_Safe_Call Evas_Safe_Call;
|
|
|
|
struct _Evas_Safe_Call
|
|
|
|
{
|
|
|
|
Eina_Condition c;
|
|
|
|
Eina_Lock m;
|
|
|
|
|
|
|
|
int current_id;
|
|
|
|
};
|
|
|
|
|
|
|
|
static Eina_Lock _thread_mutex;
|
|
|
|
static Eina_Condition _thread_cond;
|
|
|
|
|
|
|
|
static Eina_Lock _thread_feedback_mutex;
|
|
|
|
static Eina_Condition _thread_feedback_cond;
|
|
|
|
|
|
|
|
static int _thread_loop = 0;
|
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
static Eina_Spinlock _thread_id_lock;
|
2013-05-29 23:42:56 -07:00
|
|
|
static int _thread_id = -1;
|
|
|
|
static int _thread_id_max = 0;
|
|
|
|
static int _thread_id_update = 0;
|
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
static Eina_Bool _write_error = EINA_TRUE;
|
|
|
|
static Eina_Bool _read_error = EINA_TRUE;
|
2013-01-05 17:58:50 -08:00
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
static Eina_Spinlock async_lock;
|
2013-01-05 17:58:50 -08:00
|
|
|
static Eina_Inarray async_queue;
|
|
|
|
static Evas_Event_Async *async_queue_cache = NULL;
|
|
|
|
static unsigned int async_queue_cache_max = 0;
|
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
static Ecore_Pipe *_async_pipe = NULL;
|
|
|
|
static int _event_count = 0;
|
|
|
|
|
|
|
|
|
2013-01-05 17:58:50 -08:00
|
|
|
static int _init_evas_event = 0;
|
2017-04-20 19:30:05 -07:00
|
|
|
static const int wakeup = 1;
|
|
|
|
|
|
|
|
static void _evas_async_events_fd_blocking_set(Eina_Bool blocking EINA_UNUSED);
|
|
|
|
|
|
|
|
static void
|
|
|
|
_async_events_pipe_read_cb(void *data EINA_UNUSED, void *buf, unsigned int len)
|
|
|
|
{
|
ecore_pipe: remove null check condition and fix segfualt on Windows
Summary:
This reverts commit 4917910b4911905236fa099bbc16b833b056ca07.
4917910b break backward compatibility.
Reproduction:
void pipe_handler(...);
pipe = ecore_pipe_add(pipe_handler, NULL);
ecore_pipe_write(pipe, NULL, 0);
Because of the null check condition, pipe_handler isn't called after 4917910b.
Some apps behavior which is written to expected to call pipe_handler was broken.
also, this patch fixed segfault during build on Windows
Test Plan: make on Windows
Reviewers: raster, zmike, vtorri
Reviewed By: zmike, vtorri
Subscribers: woohyun, cedric, #reviewers, #committers, zmike, vtorri
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D6824
2018-08-17 09:42:35 -07:00
|
|
|
if (!buf || wakeup != *(int*)buf || sizeof(int) != len)
|
2017-04-20 19:30:05 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
Evas_Event_Async *ev;
|
|
|
|
unsigned int ln, max;
|
|
|
|
int nr;
|
|
|
|
|
|
|
|
eina_spinlock_take(&async_lock);
|
|
|
|
|
|
|
|
ev = async_queue.members;
|
|
|
|
async_queue.members = async_queue_cache;
|
|
|
|
async_queue_cache = ev;
|
|
|
|
|
|
|
|
max = async_queue.max;
|
|
|
|
async_queue.max = async_queue_cache_max;
|
|
|
|
async_queue_cache_max = max;
|
|
|
|
|
|
|
|
ln = async_queue.len;
|
|
|
|
async_queue.len = 0;
|
|
|
|
|
|
|
|
eina_spinlock_release(&async_lock);
|
|
|
|
|
|
|
|
DBG("Evas async events queue length: %u", len);
|
|
|
|
nr = ln;
|
|
|
|
|
|
|
|
while (ln > 0)
|
|
|
|
{
|
|
|
|
if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
|
|
|
|
ev++;
|
|
|
|
ln--;
|
|
|
|
}
|
|
|
|
_event_count += nr;
|
|
|
|
|
|
|
|
_evas_async_events_fd_blocking_set(EINA_FALSE);
|
|
|
|
}
|
2013-01-05 17:58:50 -08:00
|
|
|
|
2017-11-07 15:45:03 -08:00
|
|
|
static void
|
|
|
|
_evas_async_events_fork_handle(void *data EINA_UNUSED)
|
|
|
|
{
|
|
|
|
ecore_pipe_del(_async_pipe);
|
|
|
|
_async_pipe = ecore_pipe_add(_async_events_pipe_read_cb, NULL);
|
|
|
|
}
|
|
|
|
|
2008-04-30 05:21:31 -07:00
|
|
|
int
|
|
|
|
evas_async_events_init(void)
|
|
|
|
{
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2016-11-22 21:56:44 -08:00
|
|
|
if (_init_evas_event++)
|
|
|
|
return _init_evas_event;
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2017-11-07 15:45:03 -08:00
|
|
|
ecore_fork_reset_callback_add(_evas_async_events_fork_handle, NULL);
|
2013-01-05 17:58:50 -08:00
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
_async_pipe = ecore_pipe_add(_async_events_pipe_read_cb, NULL);
|
|
|
|
if ( !_async_pipe )
|
2008-04-30 05:21:31 -07:00
|
|
|
{
|
2017-04-20 19:30:05 -07:00
|
|
|
_init_evas_event = 0;
|
|
|
|
return 0;
|
2008-04-30 05:21:31 -07:00
|
|
|
}
|
2017-02-07 18:26:26 -08:00
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
_read_error = EINA_FALSE;
|
|
|
|
_write_error = EINA_FALSE;
|
2017-02-07 18:26:26 -08:00
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_new(&async_lock);
|
2012-12-30 15:39:11 -08:00
|
|
|
eina_inarray_step_set(&async_queue, sizeof (Eina_Inarray), sizeof (Evas_Event_Async), 16);
|
|
|
|
|
2013-05-29 23:42:56 -07:00
|
|
|
eina_lock_new(&_thread_mutex);
|
|
|
|
eina_condition_new(&_thread_cond, &_thread_mutex);
|
|
|
|
|
|
|
|
eina_lock_new(&_thread_feedback_mutex);
|
|
|
|
eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex);
|
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_new(&_thread_id_lock);
|
2013-05-29 23:42:56 -07:00
|
|
|
|
2008-04-30 05:21:31 -07:00
|
|
|
return _init_evas_event;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
evas_async_events_shutdown(void)
|
|
|
|
{
|
2016-11-22 21:56:44 -08:00
|
|
|
if (--_init_evas_event)
|
|
|
|
return _init_evas_event;
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2013-05-29 23:42:56 -07:00
|
|
|
eina_condition_free(&_thread_cond);
|
|
|
|
eina_lock_free(&_thread_mutex);
|
|
|
|
eina_condition_free(&_thread_feedback_cond);
|
|
|
|
eina_lock_free(&_thread_feedback_mutex);
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_free(&_thread_id_lock);
|
2013-05-29 23:42:56 -07:00
|
|
|
|
2016-11-22 21:56:44 -08:00
|
|
|
free(async_queue_cache);
|
|
|
|
async_queue_cache = NULL;
|
2017-09-25 22:26:56 -07:00
|
|
|
async_queue_cache_max = 0;
|
2016-11-22 21:56:44 -08:00
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_free(&async_lock);
|
2013-01-05 17:58:50 -08:00
|
|
|
eina_inarray_flush(&async_queue);
|
|
|
|
|
2017-11-07 15:45:03 -08:00
|
|
|
ecore_fork_reset_callback_del(_evas_async_events_fork_handle, NULL);
|
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
ecore_pipe_del(_async_pipe);
|
|
|
|
_read_error = EINA_TRUE;
|
|
|
|
_write_error = EINA_TRUE;
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2008-04-30 05:21:31 -07:00
|
|
|
return _init_evas_event;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_async_events_fd_get(void)
|
|
|
|
{
|
2018-04-10 14:39:21 -07:00
|
|
|
return -1;
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_async_events_process(void)
|
|
|
|
{
|
2017-04-20 19:30:05 -07:00
|
|
|
int count = 0;
|
2017-11-07 15:45:03 -08:00
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
if (_read_error) return -1;
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2017-04-20 19:30:05 -07:00
|
|
|
_event_count = 0;
|
|
|
|
while (ecore_pipe_wait(_async_pipe, 1, 0.0))
|
2017-05-11 22:41:49 -07:00
|
|
|
count = _event_count;
|
2012-12-18 08:26:44 -08:00
|
|
|
|
2008-04-30 05:21:31 -07:00
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2012-12-18 08:26:44 -08:00
|
|
|
static void
|
|
|
|
_evas_async_events_fd_blocking_set(Eina_Bool blocking)
|
|
|
|
{
|
2013-03-10 07:09:45 -07:00
|
|
|
#ifdef HAVE_FCNTL
|
2017-04-20 19:30:05 -07:00
|
|
|
int _fd_read = ecore_pipe_read_fd(_async_pipe);
|
2012-12-18 08:26:44 -08:00
|
|
|
long flags = fcntl(_fd_read, F_GETFL);
|
|
|
|
|
|
|
|
if (blocking) flags &= ~O_NONBLOCK;
|
|
|
|
else flags |= O_NONBLOCK;
|
|
|
|
|
2014-08-27 00:39:09 -07:00
|
|
|
if (fcntl(_fd_read, F_SETFL, flags) < 0) ERR("cannot set fd flags");
|
2013-03-10 03:45:24 -07:00
|
|
|
#else
|
|
|
|
(void) blocking;
|
|
|
|
#endif
|
2012-12-18 08:26:44 -08:00
|
|
|
}
|
|
|
|
|
2013-06-03 22:07:18 -07:00
|
|
|
EAPI int
|
2012-12-18 08:26:44 -08:00
|
|
|
evas_async_events_process_blocking(void)
|
|
|
|
{
|
|
|
|
int ret;
|
2017-04-20 19:30:05 -07:00
|
|
|
if (_read_error) return -1;
|
2012-12-18 08:26:44 -08:00
|
|
|
|
|
|
|
_evas_async_events_fd_blocking_set(EINA_TRUE);
|
2017-04-20 19:30:05 -07:00
|
|
|
|
|
|
|
_event_count = 0;
|
|
|
|
ecore_pipe_wait(_async_pipe, 1, 0.0);
|
|
|
|
ret = _event_count;
|
|
|
|
|
2012-12-18 08:26:44 -08:00
|
|
|
_evas_async_events_fd_blocking_set(EINA_FALSE);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-06-17 03:01:52 -07:00
|
|
|
EAPI Eina_Bool
|
2010-08-28 18:59:21 -07:00
|
|
|
evas_async_events_put(const void *target, Evas_Callback_Type type, void *event_info, Evas_Async_Events_Put_Cb func)
|
2008-04-30 05:21:31 -07:00
|
|
|
{
|
2009-09-27 20:51:21 -07:00
|
|
|
Evas_Event_Async *ev;
|
2013-01-09 04:22:52 -08:00
|
|
|
unsigned int count;
|
2017-04-20 19:30:05 -07:00
|
|
|
Eina_Bool ret = EINA_TRUE;;
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2013-01-05 17:58:50 -08:00
|
|
|
if (!func) return EINA_FALSE;
|
2017-04-20 19:30:05 -07:00
|
|
|
if (_write_error) return EINA_FALSE;
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_take(&async_lock);
|
2012-12-30 15:39:11 -08:00
|
|
|
|
|
|
|
count = async_queue.len;
|
2012-12-30 17:27:58 -08:00
|
|
|
ev = eina_inarray_grow(&async_queue, 1);
|
2013-01-05 17:58:50 -08:00
|
|
|
if (!ev)
|
2012-12-30 15:39:11 -08:00
|
|
|
{
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_release(&async_lock);
|
2013-01-05 17:58:50 -08:00
|
|
|
return EINA_FALSE;
|
2012-12-30 15:39:11 -08:00
|
|
|
}
|
|
|
|
|
2013-01-05 17:58:50 -08:00
|
|
|
ev->func = func;
|
|
|
|
ev->target = target;
|
|
|
|
ev->type = type;
|
|
|
|
ev->event_info = event_info;
|
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_release(&async_lock);
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2013-01-05 17:58:50 -08:00
|
|
|
if (count == 0)
|
2011-10-20 22:50:05 -07:00
|
|
|
{
|
2017-04-20 19:30:05 -07:00
|
|
|
if (!ecore_pipe_write(_async_pipe, &wakeup, sizeof(int)))
|
2013-01-09 04:22:52 -08:00
|
|
|
{
|
|
|
|
ret = EINA_FALSE;
|
2017-04-20 19:30:05 -07:00
|
|
|
_write_error = EINA_TRUE;
|
2013-01-09 04:22:52 -08:00
|
|
|
}
|
2011-10-20 22:50:05 -07:00
|
|
|
}
|
2011-10-22 23:59:40 -07:00
|
|
|
|
2013-01-09 04:22:52 -08:00
|
|
|
return ret;
|
2008-04-30 05:21:31 -07:00
|
|
|
}
|
2013-05-29 23:42:56 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_evas_thread_main_loop_lock(void *target EINA_UNUSED,
|
|
|
|
Evas_Callback_Type type EINA_UNUSED,
|
|
|
|
void *event_info)
|
|
|
|
{
|
|
|
|
Evas_Safe_Call *call = event_info;
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_mutex);
|
|
|
|
|
|
|
|
eina_lock_take(&call->m);
|
|
|
|
_thread_id = call->current_id;
|
|
|
|
eina_condition_broadcast(&call->c);
|
|
|
|
eina_lock_release(&call->m);
|
|
|
|
|
|
|
|
while (_thread_id_update != _thread_id)
|
|
|
|
eina_condition_wait(&_thread_cond);
|
|
|
|
eina_lock_release(&_thread_mutex);
|
|
|
|
|
|
|
|
eina_main_loop_define();
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_feedback_mutex);
|
|
|
|
|
|
|
|
_thread_id = -1;
|
|
|
|
|
|
|
|
eina_condition_broadcast(&_thread_feedback_cond);
|
|
|
|
eina_lock_release(&_thread_feedback_mutex);
|
|
|
|
|
|
|
|
eina_condition_free(&call->c);
|
|
|
|
eina_lock_free(&call->m);
|
|
|
|
free(call);
|
2016-11-21 21:33:48 -08:00
|
|
|
}
|
2013-05-29 23:42:56 -07:00
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_thread_main_loop_begin(void)
|
|
|
|
{
|
|
|
|
Evas_Safe_Call *order;
|
|
|
|
|
|
|
|
if (eina_main_loop_is())
|
|
|
|
{
|
|
|
|
return ++_thread_loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
order = malloc(sizeof (Evas_Safe_Call));
|
|
|
|
if (!order) return -1;
|
|
|
|
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_take(&_thread_id_lock);
|
2013-05-29 23:42:56 -07:00
|
|
|
order->current_id = ++_thread_id_max;
|
|
|
|
if (order->current_id < 0)
|
|
|
|
{
|
|
|
|
_thread_id_max = 0;
|
|
|
|
order->current_id = ++_thread_id_max;
|
|
|
|
}
|
2013-10-10 01:44:24 -07:00
|
|
|
eina_spinlock_release(&_thread_id_lock);
|
2013-05-29 23:42:56 -07:00
|
|
|
|
|
|
|
eina_lock_new(&order->m);
|
|
|
|
eina_condition_new(&order->c, &order->m);
|
|
|
|
|
|
|
|
evas_async_events_put(NULL, 0, order, _evas_thread_main_loop_lock);
|
|
|
|
|
|
|
|
eina_lock_take(&order->m);
|
|
|
|
while (order->current_id != _thread_id)
|
|
|
|
eina_condition_wait(&order->c);
|
|
|
|
eina_lock_release(&order->m);
|
|
|
|
|
|
|
|
eina_main_loop_define();
|
|
|
|
|
|
|
|
_thread_loop = 1;
|
|
|
|
|
|
|
|
return _thread_loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
EAPI int
|
|
|
|
evas_thread_main_loop_end(void)
|
|
|
|
{
|
|
|
|
int current_id;
|
|
|
|
|
|
|
|
if (_thread_loop == 0)
|
|
|
|
abort();
|
|
|
|
|
|
|
|
/* until we unlock the main loop, this thread has the main loop id */
|
|
|
|
if (!eina_main_loop_is())
|
|
|
|
{
|
|
|
|
ERR("Not in a locked thread !");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_thread_loop--;
|
|
|
|
if (_thread_loop > 0)
|
|
|
|
return _thread_loop;
|
|
|
|
|
|
|
|
current_id = _thread_id;
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_mutex);
|
|
|
|
_thread_id_update = _thread_id;
|
|
|
|
eina_condition_broadcast(&_thread_cond);
|
|
|
|
eina_lock_release(&_thread_mutex);
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_feedback_mutex);
|
|
|
|
while (current_id == _thread_id && _thread_id != -1)
|
|
|
|
eina_condition_wait(&_thread_feedback_cond);
|
|
|
|
eina_lock_release(&_thread_feedback_mutex);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|