summaryrefslogtreecommitdiff
path: root/src/lib/ecore
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/ecore')
-rw-r--r--src/lib/ecore/Ecore.h15
-rw-r--r--src/lib/ecore/Ecore_Common.h18
-rw-r--r--src/lib/ecore/Ecore_Eo.h12
-rw-r--r--src/lib/ecore/Ecore_Getopt.h2
-rw-r--r--src/lib/ecore/Ecore_Legacy.h20
-rw-r--r--src/lib/ecore/Efl_Core.h2
-rw-r--r--src/lib/ecore/ecore.c116
-rw-r--r--src/lib/ecore/ecore_anim.c137
-rw-r--r--src/lib/ecore/ecore_exe_eo.h6
-rw-r--r--src/lib/ecore/ecore_exe_posix.c100
-rw-r--r--src/lib/ecore/ecore_internal.h33
-rw-r--r--src/lib/ecore/ecore_main.c40
-rw-r--r--src/lib/ecore/ecore_main_timechanges.c2
-rw-r--r--src/lib/ecore/ecore_pipe.c3
-rw-r--r--src/lib/ecore/ecore_private.h10
-rw-r--r--src/lib/ecore/ecore_thread.c3
-rw-r--r--src/lib/ecore/ecore_time.c32
-rw-r--r--src/lib/ecore/efl_core_proc_env.c6
-rw-r--r--src/lib/ecore/efl_cubic_bezier_interpolator.eo2
-rw-r--r--src/lib/ecore/efl_exe.c185
-rw-r--r--src/lib/ecore/efl_exe.eo12
-rw-r--r--src/lib/ecore/efl_filter_model.c35
-rw-r--r--src/lib/ecore/efl_io_copier.eo4
-rw-r--r--src/lib/ecore/efl_loop.c6
-rw-r--r--src/lib/ecore/efl_loop_consumer.eo2
-rw-r--r--src/lib/ecore/efl_loop_model.c36
-rw-r--r--src/lib/ecore/efl_loop_model.eo1
-rw-r--r--src/lib/ecore/efl_thread.c4
-rw-r--r--src/lib/ecore/efl_threadio.eo2
-rw-r--r--src/lib/ecore/meson.build25
30 files changed, 635 insertions, 236 deletions
diff --git a/src/lib/ecore/Ecore.h b/src/lib/ecore/Ecore.h
index 7818faf907..e87ccc6093 100644
--- a/src/lib/ecore/Ecore.h
+++ b/src/lib/ecore/Ecore.h
@@ -6,7 +6,7 @@
/**
* @page ecore_main Ecore
* @date 2000 (created)
- * @section toc Table of Contents
+ * @section ecore_toc Table of Contents
* @li @ref ecore_main_intro
* @li @ref ecore_main_compiling
* @li @ref ecore_main_next_steps
@@ -45,15 +45,16 @@
* this is very simple. You simply have to compile your application
* with the appropriate compiler flags that the @p pkg-config script
* outputs. Note that each module is separate in pkg-config. For
- * example using @ref Ecore_Evas_Group:
+ * example using @c Ecore_Evas:
+ *
* Compiling C or C++ files into object files:
- * @verbatim
+ * @code
* gcc -c -o main.o main.c `pkg-config --cflags ecore ecore-evas`
- * @endverbatim
+ * @endcode
* Linking object files into a binary executable:
- * @verbatim
+ * @code
* gcc -o my_application main.o `pkg-config --libs ecore ecore-evas`
- * @endverbatim
+ * @endcode
* See @ref pkgconfig
*
* @section ecore_main_next_steps Next Steps
@@ -330,6 +331,8 @@ extern "C" {
#endif
#include "Ecore_Eo.h"
+EAPI double _ecore_main_loop_wakeup_time_get(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/lib/ecore/Ecore_Common.h b/src/lib/ecore/Ecore_Common.h
index 443a05880c..899debc267 100644
--- a/src/lib/ecore/Ecore_Common.h
+++ b/src/lib/ecore/Ecore_Common.h
@@ -4,8 +4,8 @@
#include <Efl_Config.h>
/**
- * @ingroup Ecore
* @defgroup Ecore_Init_Group Ecore initialization, shutdown functions and reset on fork.
+ * @ingroup Ecore
* @{
*/
@@ -2660,8 +2660,8 @@ EAPI double ecore_throttle_get(void);
*/
/**
- * @ingroup Ecore_Main_Loop_Group
* @defgroup Ecore_Poller_Group Ecore Poll functions
+ * @ingroup Ecore_Main_Loop_Group
*
* Ecore poller provides infrastructure for the creation of pollers. Pollers
* are, in essence, callbacks that share a single timer per type. Because not
@@ -2732,16 +2732,12 @@ EAPI double ecore_throttle_get(void);
* @{
*/
-/**
- * @enum _Ecore_Animator_Source
- * Defines the timing sources for animators.
- */
-enum _Ecore_Animator_Source /* Timing sources for animators */
+/** Defines the timing sources for animators. */
+typedef enum
{
ECORE_ANIMATOR_SOURCE_TIMER, /**< The default system clock/timer based animator that ticks every "frametime" seconds */
ECORE_ANIMATOR_SOURCE_CUSTOM /**< A custom animator trigger that you need to call ecore_animator_custom_tick() to make it tick */
-};
-typedef enum _Ecore_Animator_Source Ecore_Animator_Source;
+} Ecore_Animator_Source;
/**
* @typedef Ecore_Timeline_Cb Ecore_Timeline_Cb
@@ -2798,7 +2794,7 @@ typedef enum
* @warning Too small a value may cause performance issues and too high a
* value may cause your animation to seem "jerky".
*
- * @note The default @p frametime value is 1/30th of a second.
+ * @note The default @p frametime value is 1/60th of a second.
*/
EAPI void ecore_animator_frametime_set(double frametime);
@@ -2950,7 +2946,7 @@ EAPI double ecore_animator_pos_map_n(double pos, Ecore_Pos_Map map, int v_size,
* on the animator source. The default source is the system clock timer
* source - ECORE_ANIMATOR_SOURCE_TIMER. This source uses the system clock
* to tick over every N seconds (specified by ecore_animator_frametime_set(),
- * with the default being 1/30th of a second unless set otherwise). You can
+ * with the default being 1/60th of a second unless set otherwise). You can
* set a custom tick source by setting the source to
* ECORE_ANIMATOR_SOURCE_CUSTOM and then drive it yourself based on some input
* tick source (like another application via ipc, some vertical blanking
diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h
index 02b44f3482..90a0cc38e5 100644
--- a/src/lib/ecore/Ecore_Eo.h
+++ b/src/lib/ecore/Ecore_Eo.h
@@ -5,7 +5,7 @@
#include <Eo.h>
/**
- * @ingroup Ecore_Timer_Group
+ * @addtogroup Ecore_Timer_Group
*
* @{
*/
@@ -21,7 +21,7 @@
#include "efl_loop_message_future_handler.eo.h"
/**
- * @ingroup Ecore_MainLoop_Group
+ * @addtogroup Ecore_Main_Loop_Group
*
* @{
*/
@@ -68,7 +68,7 @@ EAPI int efl_loop_exit_code_process(Eina_Value *value);
/**
* @brief Get the future scheduler for the current loop.
*
- * @param[in] An object which is either a loop or a loop consumer
+ * @param[in] obj An object which is either a loop or a loop consumer
* @return The current loop's future scheduler.
*/
EAPI Eina_Future_Scheduler *efl_loop_future_scheduler_get(const Eo *obj);
@@ -93,7 +93,8 @@ EAPI Eo *efl_main_loop_get(void);
*/
/**
- * @ingroup Ecore_Fd_Io_Group
+ * @ingroup Ecore
+ * @addtogroup Ecore_Fd_Io_Group
*
* @{
*/
@@ -115,7 +116,8 @@ EAPI Eo *efl_main_loop_get(void);
*/
/**
- * @ingroup Ecore_Model_Group
+ * @ingroup Ecore
+ * @addtogroup Ecore_Model_Group
*
* @{
*/
diff --git a/src/lib/ecore/Ecore_Getopt.h b/src/lib/ecore/Ecore_Getopt.h
index 7a038f744a..751d30c788 100644
--- a/src/lib/ecore/Ecore_Getopt.h
+++ b/src/lib/ecore/Ecore_Getopt.h
@@ -1186,7 +1186,7 @@ EAPI Eina_List *ecore_getopt_list_free(Eina_List *list);
* @return @c EINA_TRUE on success, @c EINA_FALSE on incorrect geometry value.
*
* This is a helper function to be used with ECORE_GETOPT_CALLBACK_*().
- *
+ *
* @c callback_data value is ignored, you can safely use @c NULL.
*/
EAPI Eina_Bool ecore_getopt_callback_geometry_parse(const Ecore_Getopt *parser, const Ecore_Getopt_Desc *desc, const char *str, void *data, Ecore_Getopt_Value *storage);
diff --git a/src/lib/ecore/Ecore_Legacy.h b/src/lib/ecore/Ecore_Legacy.h
index 9c951f5a93..e4ed2773c1 100644
--- a/src/lib/ecore/Ecore_Legacy.h
+++ b/src/lib/ecore/Ecore_Legacy.h
@@ -2,7 +2,7 @@
#define _ECORE_LEGACY_H
/**
- * @ingroup Ecore_Poller_Group
+ * @addtogroup Ecore_Poller_Group
*
* @{
*/
@@ -76,8 +76,6 @@ EAPI double ecore_poller_poll_interval_get(Ecore_Poller_Type type);
* @param[in] interval The tick interval; must be a power of 2 and <= 32768.
*
* @return @c true on success, @c false on failure.
- *
- * @ingroup Ecore_Poller
*/
EAPI Eina_Bool ecore_poller_poller_interval_set(Ecore_Poller *obj, int interval);
@@ -85,8 +83,6 @@ EAPI Eina_Bool ecore_poller_poller_interval_set(Ecore_Poller *obj, int interval)
* @brief Polling interval rate of the poller.
*
* @return The tick interval; must be a power of 2 and <= 32768.
- *
- * @ingroup Ecore_Poller
*/
EAPI int ecore_poller_poller_interval_get(const Ecore_Poller *obj);
@@ -95,11 +91,15 @@ EAPI int ecore_poller_poller_interval_get(const Ecore_Poller *obj);
*/
/**
- * @ingroup Ecore_Animator_Group
+ * @addtogroup Ecore_Animator_Group
*
* @{
*/
+/**
+ * @struct Ecore_Animator
+ * Opaque handle to manage Ecore Animator objects.
+ */
typedef struct _Ecore_Animator Ecore_Animator;
/**
@@ -205,7 +205,7 @@ EAPI void ecore_animator_thaw(Ecore_Animator *animator);
*/
/**
- * @ingroup Ecore_Timer_Group
+ * @addtogroup Ecore_Timer_Group
*
* @{
*/
@@ -302,7 +302,7 @@ EAPI void ecore_timer_thaw(Ecore_Timer *timer);
*/
/**
- * @ingroup Ecore_Idle_Group
+ * @addtogroup Ecore_Idle_Group
*
* @{
*/
@@ -387,7 +387,7 @@ EAPI void *ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter);
*/
/**
- * @ingroup Ecore_Exe_Group
+ * @addtogroup Ecore_Exe_Group
*
* @{
*/
@@ -399,7 +399,7 @@ EAPI void *ecore_idle_exiter_del(Ecore_Idle_Exiter *idle_exiter);
*/
/**
- * @ingroup Ecore_Job_Group
+ * @addtogroup Ecore_Job_Group
*
* @{
*/
diff --git a/src/lib/ecore/Efl_Core.h b/src/lib/ecore/Efl_Core.h
index 0178299379..7e80819b83 100644
--- a/src/lib/ecore/Efl_Core.h
+++ b/src/lib/ecore/Efl_Core.h
@@ -54,7 +54,7 @@
extern "C" {
#endif
-extern EAPI double _efl_startup_time;
+EAPI extern double _efl_startup_time;
#include "Ecore_Common.h"
#include "Ecore_Eo.h"
diff --git a/src/lib/ecore/ecore.c b/src/lib/ecore/ecore.c
index 3110c5ef54..0b4ba4a8fd 100644
--- a/src/lib/ecore/ecore.c
+++ b/src/lib/ecore/ecore.c
@@ -21,10 +21,6 @@
# include <sys/mman.h>
#endif
-#ifdef HAVE_SYSTEMD
-# include <systemd/sd-daemon.h>
-#endif
-
#ifdef _WIN32
# include <evil_private.h> /* evil_init/shutdown */
#endif
@@ -36,8 +32,8 @@
#include "ecore_private.h"
#include "../../static_libs/buildsystem/buildsystem.h"
-#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO)
-#include <malloc.h>
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO) || defined(HAVE_MALLINFO2)
+# include <malloc.h>
#endif
#ifndef O_BINARY
@@ -49,14 +45,19 @@ EAPI Ecore_Version *ecore_version = &_version;
EAPI double _efl_startup_time = 0;
-#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO)
-#define KEEP_MAX(Global, Local) \
- if (Global < (Local)) \
- Global = Local;
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO) || defined(HAVE_MALLINFO2)
+# define KEEP_MAX(Global, Local) \
+ if (Global < (Local)) \
+ Global = Local;
static Eina_Bool _ecore_memory_statistic(void *data);
+# ifdef HAVE_MALLINFO2
+static size_t _ecore_memory_max_total = 0;
+static size_t _ecore_memory_max_free = 0;
+# else
static int _ecore_memory_max_total = 0;
static int _ecore_memory_max_free = 0;
+# endif
static pid_t _ecore_memory_pid = 0;
#ifdef HAVE_MALLOC_INFO
static FILE *_ecore_memory_statistic_file = NULL;
@@ -295,7 +296,7 @@ ecore_init(void)
if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate();
#endif
-#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO)
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO) || defined(HAVE_MALLINFO2)
if (getenv("ECORE_MEM_STAT"))
{
#ifdef HAVE_MALLOC_INFO
@@ -313,9 +314,7 @@ ecore_init(void)
#ifdef HAVE_SYSTEMD
if (getenv("WATCHDOG_USEC"))
{
- double sec;
-
- sec = ((double) atoi(getenv("WATCHDOG_USEC"))) / 1000 / 1000;
+ double sec = ((double) atoi(getenv("WATCHDOG_USEC"))) / 1000 / 1000;
_systemd_watchdog =
efl_add(EFL_LOOP_TIMER_CLASS, efl_main_loop_get(),
@@ -326,7 +325,6 @@ ecore_init(void)
unsetenv("WATCHDOG_USEC");
INF("Setup systemd watchdog to : %f", sec);
-
_systemd_watchdog_cb(NULL, NULL);
}
#endif
@@ -439,16 +437,22 @@ ecore_shutdown(void)
_ecore_main_loop_shutdown();
-#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO)
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO) || defined(HAVE_MALLINFO2)
if (getenv("ECORE_MEM_STAT"))
{
_ecore_memory_statistic(NULL);
+ #ifdef HAVE_MALLINFO2
+ ERR("[%i] Memory MAX total: %lu, free: %lu",
+ _ecore_memory_pid,
+ _ecore_memory_max_total,
+ _ecore_memory_max_free);
+ #else
ERR("[%i] Memory MAX total: %i, free: %i",
_ecore_memory_pid,
_ecore_memory_max_total,
_ecore_memory_max_free);
-
+ #endif
#ifdef HAVE_MALLOC_INFO
fclose(_ecore_memory_statistic_file);
@@ -589,7 +593,7 @@ ecore_fork_reset(void)
fcb->func(fcb->data);
}
fork_cbs_walking--;
-
+
EINA_LIST_FOREACH_SAFE(fork_cbs, l, ln, fcb)
{
if (fcb->delete_me)
@@ -962,24 +966,38 @@ _ecore_fps_debug_runtime_add(double t)
static void
_systemd_watchdog_cb(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED)
{
- sd_notify(0, "WATCHDOG=1");
+ if (getenv("NOTIFY_SOCKET"))
+ {
+ _ecore_sd_init();
+ if (_ecore_sd_notify) _ecore_sd_notify(0, "WATCHDOG=1");
+ }
}
#endif
-#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO)
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLOC_INFO) || defined(HAVE_MALLINFO2)
static Eina_Bool
_ecore_memory_statistic(EINA_UNUSED void *data)
{
#ifdef HAVE_MALLOC_INFO
static int frame = 0;
#endif
-#ifdef HAVE_MALLINFO
+
+#if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
+ Eina_Bool changed = EINA_FALSE;
+
+# if defined(HAVE_MALLINFO2)
+ struct mallinfo2 mi;
+ static size_t uordblks = 0;
+ static size_t fordblks = 0;
+
+ mi = mallinfo2();
+# else
struct mallinfo mi;
static int uordblks = 0;
static int fordblks = 0;
- Eina_Bool changed = EINA_FALSE;
mi = mallinfo();
+# endif
#define HAS_CHANGED(Global, Local) \
if (Global != Local) \
@@ -992,14 +1010,24 @@ _ecore_memory_statistic(EINA_UNUSED void *data)
HAS_CHANGED(fordblks, mi.fordblks);
if (changed)
- ERR("[%i] Memory total: %i, free: %i",
- _ecore_memory_pid,
- mi.uordblks,
- mi.fordblks);
+ {
+#ifdef HAVE_MALLINFO2
+ ERR("[%i] Memory total: %lu, free: %lu",
+ _ecore_memory_pid,
+ mi.uordblks,
+ mi.fordblks);
+#else
+ ERR("[%i] Memory total: %i, free: %i",
+ _ecore_memory_pid,
+ mi.uordblks,
+ mi.fordblks);
+#endif
+ }
KEEP_MAX(_ecore_memory_max_total, mi.uordblks);
KEEP_MAX(_ecore_memory_max_free, mi.fordblks);
#endif
+
#ifdef HAVE_MALLOC_INFO
if (frame) fputs("\n", _ecore_memory_statistic_file);
malloc_info(0, _ecore_memory_statistic_file);
@@ -1122,3 +1150,39 @@ ecore_memory_state_set(Ecore_Memory_State state)
_ecore_memory_state = state;
ecore_event_add(ECORE_EVENT_MEMORY_STATE, NULL, NULL, NULL);
}
+
+#ifdef HAVE_SYSTEMD
+static Eina_Module *_libsystemd = NULL;
+static Eina_Bool _libsystemd_broken = EINA_FALSE;
+
+int (*_ecore_sd_notify) (int unset_environment, const char *state) = NULL;
+
+void
+_ecore_sd_init(void)
+{
+ if (_libsystemd_broken) return;
+ _libsystemd = eina_module_new("libsystemd.so.0");
+ if (_libsystemd)
+ {
+ if (!eina_module_load(_libsystemd))
+ {
+ eina_module_free(_libsystemd);
+ _libsystemd = NULL;
+ }
+ }
+ if (!_libsystemd)
+ {
+ _libsystemd_broken = EINA_TRUE;
+ return;
+ }
+ _ecore_sd_notify =
+ eina_module_symbol_get(_libsystemd, "sd_notify");
+ if (!_ecore_sd_notify)
+ {
+ _ecore_sd_notify = NULL;
+ eina_module_free(_libsystemd);
+ _libsystemd = NULL;
+ _libsystemd_broken = EINA_TRUE;
+ }
+}
+#endif
diff --git a/src/lib/ecore/ecore_anim.c b/src/lib/ecore/ecore_anim.c
index f2ec2d61c8..a5bde81ff6 100644
--- a/src/lib/ecore/ecore_anim.c
+++ b/src/lib/ecore/ecore_anim.c
@@ -626,68 +626,103 @@ _pos_map_spring(double pos,
return _pos_map_sin((M_PI / 2.0) + (p2 * len)) * decay;
}
-static double
-_cubic_bezier_a (double a1, double a2)
+static inline double
+cuberoot(double v)
{
- return 1.0 - 3.0 * a2 + 3.0 * a1;
+ if (v < 0.0)
+ return -pow(-v, 1. / 3.);
+ else
+ return pow(v, 1. / 3.);
}
static double
-_cubic_bezier_b (double a1, double a2)
+_bezier_t_get(double _x, double _x1, double _x2)
{
- return 3.0 * a2 - 6.0 * a1;
-}
+ if (_x < 0.0 || _x > 1.0) return _x;
+
+ // Cardano's algorithm
+ double\
+ pa = _x - 0.0,
+ pb = _x - _x1,
+ pc = _x - _x2,
+ pd = _x - 1.0;
+
+ double\
+ a = 3*pa-6*pb+3*pc,
+ b = -3*pa+3*pb,
+ c = pa,
+ d = -pa+3*pb-3*pc+pd;
+
+ a /= d;
+ b /= d;
+ c /= d;
+
+ double\
+ p = (3*b-a*a)/3.0,
+ p3 = p/3.0,
+ q = (2*a*a*a-9*a*b+27*c)/27.0,
+ q2 = q/2.0,
+ discriminant = q2*q2 + p3*p3*p3;
+
+ double u1, v1, root1, root2, root3;
+
+ if (discriminant < 0)
+ {
+ double\
+ mp3 = -p/3.0,
+ mp33 = mp3*mp3*mp3,
+ r = sqrt(mp33),
+ t = -q / (2*r),
+ cosphi = t<-1.0 ? -1.0 : t>1.0 ? 1.0 : t,
+ phi = acos(cosphi),
+ crtr = cuberoot(r),
+ t1 = 2*crtr;
+ root1 = t1 * cos(phi/3.0) - a/3.0;
+ root2 = t1 * cos((phi+2*M_PI)/3.0) - a/3.0;
+ root3 = t1 * cos((phi+4*M_PI)/3.0) - a/3.0;
+
+ if (root1 >= 0.0 && root1 <= 1.0) return root1;
+ if (root2 >= 0.0 && root2 <= 1.0) return root2;
+ if (root3 >= 0.0 && root3 <= 1.0) return root3;
+ }
+ else if (discriminant == 0)
+ {
+ u1 = q2 < 0 ? cuberoot(-q2) : -cuberoot(q2);
+ root1 = 2*u1 - a/3.0;
+ root2 = -u1 - a/3.0;
-static double
-_cubic_bezier_c(double a1)
-{
- return 3.0 * a1;
-}
+ if (root1 >= 0.0 && root1 <= 1.0) return root1;
+ if (root2 >= 0.0 && root2 <= 1.0) return root2;
+ }
+ else
+ {
+ double sd = sqrt(discriminant);
+ u1 = cuberoot(sd - q2);
+ v1 = cuberoot(sd + q2);
+ root1 = u1 - v1 - a/3.0;
-static double
-_cubic_bezier_calc(double t,
- double a1,
- double a2)
-{
- return ((_cubic_bezier_a(a1, a2) * t +
- _cubic_bezier_b(a1, a2)) * t +
- _cubic_bezier_c(a1)) * t;
-}
+ if (root1 >= 0.0 && root1 <= 1.0) return root1;
+ }
-static double
-_cubic_bezier_slope_get(double t,
- double a1,
- double a2)
-{
- return 3.0 * _cubic_bezier_a(a1, a2) * t * t +
- 2.0 * _cubic_bezier_b(a1, a2) * t +
- _cubic_bezier_c(a1);
+ return _x;
}
static double
-_cubic_bezier_t_get(double a,
- double x1,
- double x2)
+_bezier_calc(double t, double y1, double y2)
{
-#define APPROXIMATE_RANGE(val) \
- ((((val) < 0.01) && ((val) > -0.01)) ? EINA_TRUE : EINA_FALSE)
-
- const int LIMIT = 100;
- double current_slope;
- double change;
- double current_x;
- double guess_t = a;
-
- for (int i = 0; i < LIMIT; i++)
- {
- current_slope = _cubic_bezier_slope_get(guess_t, x1, x2);
- if (EINA_DBL_EQ(current_slope, 0.0)) return guess_t;
- current_x = _cubic_bezier_calc(guess_t, x1, x2) - a;
- change = current_x / current_slope;
- guess_t -= change;
- if (APPROXIMATE_RANGE(change)) break;
- }
- return guess_t;
+ double y0 = 0.0;
+ double y3 = 1.0;
+
+ double u = 1.0 - t;
+ double t2 = t*t;
+ double t3 = t*t*t;
+ double u2 = u*u;
+ double u3 = u*u*u;
+
+ return u3 * y0 +
+ 3.0 * u2 * t * y1 +
+ 3.0 * u * t2 * y2 +
+ t3 * y3;
}
static double
@@ -700,7 +735,7 @@ _pos_map_cubic_bezier(double pos,
if (EINA_DBL_EQ(x1, y1) &&
EINA_DBL_EQ(x2, y2))
return pos;
- return _cubic_bezier_calc(_cubic_bezier_t_get(pos, x1, x2), y1, y2);
+ return _bezier_calc(_bezier_t_get(pos, x1, x2), y1, y2);
}
#define DBL_TO(Fp) eina_f32p32_double_to(Fp)
diff --git a/src/lib/ecore/ecore_exe_eo.h b/src/lib/ecore/ecore_exe_eo.h
index fa8ecb026a..a4ab65e635 100644
--- a/src/lib/ecore/ecore_exe_eo.h
+++ b/src/lib/ecore/ecore_exe_eo.h
@@ -4,6 +4,10 @@
#ifndef _ECORE_EXE_EO_CLASS_TYPE
#define _ECORE_EXE_EO_CLASS_TYPE
+/**
+ * @struct Ecore_Exe
+ * Opaque handle to manage Ecore Exe objects.
+ */
typedef Eo Ecore_Exe;
#endif
@@ -76,7 +80,7 @@ typedef enum
*/
#define ECORE_EXE_CLASS ecore_exe_class_get()
-EWAPI const Efl_Class *ecore_exe_class_get(void);
+EWAPI const Efl_Class *ecore_exe_class_get(void) EINA_CONST;
/**
* @brief Controls the command that's executed. FIXME: May need a split/rename.
diff --git a/src/lib/ecore/ecore_exe_posix.c b/src/lib/ecore/ecore_exe_posix.c
index 44d9c73ca8..635fc0678b 100644
--- a/src/lib/ecore/ecore_exe_posix.c
+++ b/src/lib/ecore/ecore_exe_posix.c
@@ -16,6 +16,8 @@
#ifdef HAVE_PRCTL
# include <sys/prctl.h>
+#elif defined(HAVE_PROCCTL)
+# include <sys/procctl.h>
#endif
#ifdef HAVE_SYS_WAIT_H
@@ -216,6 +218,13 @@ _impl_ecore_exe_run_priority_get(void)
return run_pri;
}
+#if defined (__FreeBSD__) || defined (__OpenBSD__)
+# include <dlfcn.h>
+static char ***_dl_environ;
+#else
+extern char **environ;
+#endif
+
Eo *
_impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
{
@@ -280,31 +289,100 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
pid_t pid = 0;
volatile int vfork_exec_errno = 0;
+ sigset_t newset, oldset;
+
+ sigemptyset(&newset);
+ sigaddset(&newset, SIGPIPE);
+ sigaddset(&newset, SIGALRM);
+ sigaddset(&newset, SIGCHLD);
+ sigaddset(&newset, SIGUSR1);
+ sigaddset(&newset, SIGUSR2);
+ sigaddset(&newset, SIGHUP);
+ sigaddset(&newset, SIGQUIT);
+ sigaddset(&newset, SIGINT);
+ sigaddset(&newset, SIGTERM);
+ sigaddset(&newset, SIGBUS);
+ sigaddset(&newset, SIGCONT);
+ sigaddset(&newset, SIGWINCH);
+#ifdef SIGEMT
+ sigaddset(&newset, SIGEMT);
+#endif
+#ifdef SIGIO
+ sigaddset(&newset, SIGIO);
+#endif
+#ifdef SIGTSTP
+ sigaddset(&newset, SIGTSTP);
+#endif
+#ifdef SIGTTIN
+ sigaddset(&newset, SIGTTIN);
+#endif
+#ifdef SIGTTOU
+ sigaddset(&newset, SIGTTOU);
+#endif
+#ifdef SIGVTALRM
+ sigaddset(&newset, SIGVTALRM);
+#endif
+#ifdef SIGPWR
+ sigaddset(&newset, SIGPWR);
+#endif
+ // block all those nasty signals we don't want messing with things
+ // in signal handlers while we go from fork to exec in the child
+ pthread_sigmask(SIG_BLOCK, &newset, &oldset);
/* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */
/* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */
pid = fork();
if (pid == -1)
{
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
ERR("Failed to fork process");
pid = 0;
}
else if (pid == 0) /* child */
{
+ struct sigaction sa;
+ int sig;
+
+ sa.sa_handler = SIG_DFL;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ for (sig = 0; sig < 32; sig++) sigaction(sig, &sa, NULL);
#ifdef HAVE_SYSTEMD
- unsetenv("NOTIFY_SOCKET");
+ char **env = NULL, **e;
+
+# if defined (__FreeBSD__) || defined (__OpenBSD__)
+ _dl_environ = dlsym(NULL, "environ");
+ env = *_dl_environ;
+# else
+ env = environ;
+# endif
+ // find NOTIFY_SOCKET env var and remove it without any heap work
+ if (env)
+ {
+ Eina_Bool shuffle = EINA_FALSE;
+
+ for (e = env; *e; e++)
+ {
+ if (!shuffle)
+ {
+ if (!strncmp(e[0], "NOTIFY_SOCKET=", 14))
+ shuffle = EINA_TRUE;
+ }
+ if (shuffle) e[0] = e[1];
+ }
+ }
#endif
if (run_pri != ECORE_EXE_PRIORITY_INHERIT)
- {
-#ifdef PRIO_PROCESS
- if ((run_pri >= -20) && (run_pri <= 19))
- setpriority(PRIO_PROCESS, 0, run_pri);
+ {
+#ifdef PRIO_PROCESS
+ if ((run_pri >= -20) && (run_pri <= 19))
+ setpriority(PRIO_PROCESS, 0, run_pri);
#else
#warning "Your OS/libc does not provide PRIO_PROCESS (and possibly setpriority())"
#warning "This is a POSIX-1.2001 standard and it is highly encouraged that you"
#warning "Have support for this"
#endif
- }
+ }
if (ok && (flags & ECORE_EXE_ISOLATE_IO))
{
int devnull;
@@ -369,13 +447,15 @@ _impl_ecore_exe_efl_object_finalize(Eo *obj, Ecore_Exe_Data *exe)
except[0] = statusPipe[1];
eina_file_close_from(3, except);
/* Run the actual command. */
- _ecore_exe_exec_it(exe_cmd, flags); /* no return */
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ _ecore_exe_exec_it(exe_cmd, flags); /* no return */
}
}
_exit(-1);
}
else /* parent */
{
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
/* Close the unused pipes. */
E_NO_ERRNO(result, close(statusPipe[1]), ok);
@@ -1000,6 +1080,12 @@ _ecore_exe_exec_it(const char *exe_cmd,
{
prctl(PR_SET_PDEATHSIG, SIGTERM);
}
+#elif defined(HAVE_PROCCTL)
+ if ((flags & ECORE_EXE_TERM_WITH_PARENT))
+ {
+ int sig = SIGTERM;
+ procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig);
+ }
#endif
if (!(flags & ECORE_EXE_NOT_LEADER)) setsid();
diff --git a/src/lib/ecore/ecore_internal.h b/src/lib/ecore/ecore_internal.h
index 32a9472188..9f6e55eb24 100644
--- a/src/lib/ecore/ecore_internal.h
+++ b/src/lib/ecore/ecore_internal.h
@@ -129,6 +129,39 @@ _efl_composite_lookup(const Efl_Class *self, Eo *parent, Efl_Model *view, unsign
EFL_COMPOSITE_REMEMBER_RETURN(remember, view);
}
+/* Result from eina_future_all_* is an EINA_VALUE_TYPE_ARRAY that contain Eina_Value of
+ Eo Model. It is expected that children slice get return an EINA_VALUE_TYPE_ARRAY that
+ contain Eo Model directly.
+*/
+static inline Eina_Value
+_efl_future_all_repack(Eo *o EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v)
+{
+ unsigned int i, len;
+ Eina_Value created = EINA_VALUE_EMPTY;
+ Eina_Value r = EINA_VALUE_EMPTY;
+
+ eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4);
+
+ EINA_VALUE_ARRAY_FOREACH(&v, len, i, created)
+ {
+ Eo *target = NULL;
+
+ if (eina_value_type_get(&created) != EINA_VALUE_TYPE_OBJECT)
+ goto on_error;
+
+ target = eina_value_object_get(&created);
+ if (!target) goto on_error;
+
+ eina_value_array_append(&r, target);
+ }
+
+ return r;
+
+ on_error:
+ eina_value_flush(&r);
+ return eina_value_error_init(EFL_MODEL_ERROR_UNKNOWN);
+}
+
#undef EAPI
#define EAPI
diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c
index 7e84d9d231..a037916e3a 100644
--- a/src/lib/ecore/ecore_main.c
+++ b/src/lib/ecore/ecore_main.c
@@ -20,10 +20,6 @@
#include <fcntl.h>
#include <sys/time.h>
-#ifdef HAVE_SYSTEMD
-# include <systemd/sd-daemon.h>
-#endif
-
#ifdef HAVE_IEEEFP_H
# include <ieeefp.h> // for Solaris
#endif
@@ -211,12 +207,20 @@ static gboolean _ecore_glib_idle_enterer_called;
static gboolean ecore_fds_ready;
#endif
+static double _ecore_main_loop_wakeup_time = 0.0;
+
+EAPI double _ecore_main_loop_wakeup_time_get(void)
+{
+ return _ecore_main_loop_wakeup_time;
+}
+
static inline void
_update_loop_time(Efl_Loop_Data *pd)
{
double loop_time = ecore_time_get();
if (loop_time > pd->loop_time)
pd->loop_time = loop_time;
+ _ecore_main_loop_wakeup_time = loop_time;
}
#ifdef EFL_EXTRA_SANITY_CHECKS
@@ -316,6 +320,16 @@ _gfd_events_from_fdh(Ecore_Fd_Handler *fdh)
}
#endif
+
+static void
+_ecore_main_pre_idle_exit(void)
+{
+ // even if we never go idle, keep up flushing some of our freeq away
+ // on every idle exit which may happen if we even never called idlers
+ // for now an idea but dont enforce
+ eina_freeq_reduce(eina_freeq_main_get(), 128);
+}
+
#ifdef HAVE_LIBUV
static void
_ecore_main_uv_poll_cb(uv_poll_t *handle, int status, int events)
@@ -332,6 +346,7 @@ _ecore_main_uv_poll_cb(uv_poll_t *handle, int status, int events)
DBG("not IDLE anymore");
_ecore_main_uv_idling = EINA_FALSE;
eina_file_statgen_next();
+ _ecore_main_pre_idle_exit();
efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
_ecore_animator_run_reset();
}
@@ -532,11 +547,7 @@ _ecore_main_idler_all_call(Eo *loop, Efl_Loop_Data *pd)
{
if (pd->idlers)
efl_event_callback_call(loop, EFL_LOOP_EVENT_IDLE, NULL);
- // just spin in an idler until the free queue is empty freeing 84 items
- // from the free queue each time.for now this seems like an ok balance
- // between going in and out of a reduce func with mutexes around it
- // vs blocking mainloop for too long. this number is up for discussion
- eina_freeq_reduce(eina_freeq_main_get(), 84);
+ eina_freeq_reduce(eina_freeq_main_get(), 256);
}
#ifdef HAVE_SYS_EPOLL_H
@@ -797,6 +808,7 @@ _ecore_main_gsource_dispatch(GSource *source EINA_UNUSED,
{
_ecore_animator_run_reset();
eina_file_statgen_next();
+ _ecore_main_pre_idle_exit();
efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
ecore_idling = 0;
}
@@ -812,6 +824,7 @@ _ecore_main_gsource_dispatch(GSource *source EINA_UNUSED,
{
_ecore_animator_run_reset();
eina_file_statgen_next();
+ _ecore_main_pre_idle_exit();
efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
ecore_idling = 0;
}
@@ -872,6 +885,7 @@ _ecore_main_loop_timer_run(uv_timer_t *timer EINA_UNUSED)
{
_ecore_main_uv_idling = EINA_FALSE;
eina_file_statgen_next();
+ _ecore_main_pre_idle_exit();
efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
_ecore_animator_run_reset();
}
@@ -1186,7 +1200,11 @@ _ecore_main_loop_begin(Eo *obj, Efl_Loop_Data *pd)
if (obj == ML_OBJ)
{
#ifdef HAVE_SYSTEMD
- sd_notify(0, "READY=1");
+ if (getenv("NOTIFY_SOCKET"))
+ {
+ _ecore_sd_init();
+ if (_ecore_sd_notify) _ecore_sd_notify(0, "READY=1");
+ }
#endif
#ifdef HAVE_LIBUV
if (!_dl_uv_run)
@@ -2250,6 +2268,7 @@ _ecore_main_loop_uv_prepare(uv_prepare_t *handle EINA_UNUSED)
if (_ecore_main_uv_idling)
{
eina_file_statgen_next();
+ _ecore_main_pre_idle_exit();
efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
_ecore_animator_run_reset();
_ecore_main_uv_idling = EINA_FALSE;
@@ -2481,6 +2500,7 @@ process_all: //-*********************************************************
{
_ecore_animator_run_reset(); // XXX:
eina_file_statgen_next();
+ _ecore_main_pre_idle_exit();
efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
}
// call the fd handler per fd that became alive...
diff --git a/src/lib/ecore/ecore_main_timechanges.c b/src/lib/ecore/ecore_main_timechanges.c
index cb3daf1fc1..c2b50ec8e9 100644
--- a/src/lib/ecore/ecore_main_timechanges.c
+++ b/src/lib/ecore/ecore_main_timechanges.c
@@ -14,7 +14,7 @@
#include "Ecore.h"
#include "ecore_private.h"
-#include "lib/ecore/ecore_main_common.h"
+#include "ecore_main_common.h"
#ifdef HAVE_SYS_TIMERFD_H
diff --git a/src/lib/ecore/ecore_pipe.c b/src/lib/ecore/ecore_pipe.c
index 4023bfa70f..e884494605 100644
--- a/src/lib/ecore/ecore_pipe.c
+++ b/src/lib/ecore/ecore_pipe.c
@@ -204,6 +204,7 @@ ecore_pipe_write(Ecore_Pipe *p,
size_t already_written = 0;
int retry = ECORE_PIPE_WRITE_RETRY;
Eina_Bool ok = EINA_FALSE;
+ unsigned int bytes = nbytes;
if (!ECORE_MAGIC_CHECK(p, ECORE_MAGIC_PIPE))
{
@@ -217,7 +218,7 @@ ecore_pipe_write(Ecore_Pipe *p,
do // First write the len into the pipe
{
- ret = pipe_write(p->fd_write, &nbytes, sizeof(nbytes));
+ ret = pipe_write(p->fd_write, &bytes, sizeof(bytes));
if (ret == sizeof(nbytes))
{
retry = ECORE_PIPE_WRITE_RETRY;
diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h
index e60c191a21..f87e5e753f 100644
--- a/src/lib/ecore/ecore_private.h
+++ b/src/lib/ecore/ecore_private.h
@@ -270,7 +270,7 @@ ecore_print_warning(const char *function,
#define CHECK_PARAM_POINTER_RETURN(sparam, param, ret) \
if (!(param)) \
{ \
- ecore_print_warning(__FUNCTION__, sparam); \
+ ecore_print_warning(__func__, sparam); \
return ret; \
}
@@ -278,7 +278,7 @@ ecore_print_warning(const char *function,
#define CHECK_PARAM_POINTER(sparam, param) \
if (!(param)) \
{ \
- ecore_print_warning(__FUNCTION__, sparam); \
+ ecore_print_warning(__func__, sparam); \
return; \
}
@@ -511,6 +511,12 @@ extern Eina_Bool _ecore_glib_always_integrate;
extern Ecore_Select_Function main_loop_select;
extern int in_main_loop;
+#ifdef HAVE_SYSTEMD
+void _ecore_sd_init(void);
+
+extern int (*_ecore_sd_notify) (int unset_environment, const char *state);
+#endif
+
Eina_Bool ecore_mempool_init(void);
void ecore_mempool_shutdown(void);
#define GENERIC_ALLOC_FREE_HEADER(TYPE, Type) \
diff --git a/src/lib/ecore/ecore_thread.c b/src/lib/ecore/ecore_thread.c
index 05ab26cdea..f38c7880c1 100644
--- a/src/lib/ecore/ecore_thread.c
+++ b/src/lib/ecore/ecore_thread.c
@@ -40,6 +40,7 @@
# define PHE(x, y) eina_thread_equal(x, y)
# define PHS() eina_thread_self()
# define PHC(x, f, d) eina_thread_create(&(x), EINA_THREAD_BACKGROUND, -1, (void *)f, d)
+# define PHC2(x, f, d)eina_thread_create(&(x), EINA_THREAD_URGENT, -1, (void *)f, d)
# define PHJ(x) eina_thread_join(x)
typedef struct _Ecore_Pthread_Worker Ecore_Pthread_Worker;
@@ -953,7 +954,7 @@ ecore_thread_feedback_run(Ecore_Thread_Cb func_heavy,
eina_threads_init();
retry_direct:
- if (PHC(t, _ecore_direct_worker, worker))
+ if (PHC2(t, _ecore_direct_worker, worker))
{
SLKL(_ecore_pending_job_threads_mutex);
_ecore_thread_count_no_queue++;
diff --git a/src/lib/ecore/ecore_time.c b/src/lib/ecore/ecore_time.c
index f2afe0e860..9f039e2b59 100644
--- a/src/lib/ecore/ecore_time.c
+++ b/src/lib/ecore/ecore_time.c
@@ -13,10 +13,16 @@
#include <time.h>
+#ifdef _WIN32
+# include <evil_private.h> /* gettimeofday */
+#endif
+
#include "Ecore.h"
#include "ecore_private.h"
-#if defined (HAVE_CLOCK_GETTIME)
+#if defined(_WIN32)
+static LONGLONG _ecore_time_freq;
+#elif defined (HAVE_CLOCK_GETTIME)
static clockid_t _ecore_time_clock_id;
static Eina_Bool _ecore_time_got_clock_id = EINA_FALSE;
#elif defined(__APPLE__) && defined(__MACH__)
@@ -26,7 +32,12 @@ static double _ecore_time_clock_conversion = 1e-9;
EAPI double
ecore_time_get(void)
{
-#if defined (HAVE_CLOCK_GETTIME)
+#ifdef _WIN32
+ LARGE_INTEGER count;
+
+ QueryPerformanceCounter(&count);
+ return (double)count.QuadPart/ (double)_ecore_time_freq;
+#elif defined (HAVE_CLOCK_GETTIME)
struct timespec t;
if (EINA_UNLIKELY(!_ecore_time_got_clock_id))
@@ -39,8 +50,6 @@ ecore_time_get(void)
}
return (double)t.tv_sec + (((double)t.tv_nsec) / 1000000000.0);
-#elif defined(_WIN32)
- return evil_time_get();
#elif defined(__APPLE__) && defined(__MACH__)
return _ecore_time_clock_conversion * (double)mach_absolute_time();
#else
@@ -82,7 +91,12 @@ ecore_loop_time_set(double t)
void
_ecore_time_init(void)
{
-#if defined(HAVE_CLOCK_GETTIME)
+#if defined(_WIN32)
+ LARGE_INTEGER freq;
+
+ QueryPerformanceFrequency(&freq);
+ _ecore_time_freq = freq.QuadPart;
+#elif defined(HAVE_CLOCK_GETTIME)
struct timespec t;
if (_ecore_time_got_clock_id) return;
@@ -103,18 +117,16 @@ _ecore_time_init(void)
else
CRI("Cannot get a valid clock_gettime() clock id! Fallback to unix time");
#else
-# ifndef _WIN32
-# if defined(__APPLE__) && defined(__MACH__)
+# if defined(__APPLE__) && defined(__MACH__)
mach_timebase_info_data_t info;
kern_return_t err = mach_timebase_info(&info);
if (err == 0)
  _ecore_time_clock_conversion = 1e-9 * (double)info.numer / (double)info.denom;
else
WRN("Unable to get timebase info. Fallback to nanoseconds");
-# else
-# warning "Your platform isn't supported yet"
+# else
+# warning "Your platform isn't supported yet"
CRI("Platform does not support clock_gettime. Fallback to unix time");
-# endif
# endif
#endif
ecore_loop_time_set(ecore_time_get());
diff --git a/src/lib/ecore/efl_core_proc_env.c b/src/lib/ecore/efl_core_proc_env.c
index a4ee9d75f9..9177d822f1 100644
--- a/src/lib/ecore/efl_core_proc_env.c
+++ b/src/lib/ecore/efl_core_proc_env.c
@@ -16,7 +16,7 @@
#if defined (__FreeBSD__) || defined (__OpenBSD__)
# include <dlfcn.h>
static char ***_dl_environ;
-#else
+#elif !defined(_MSC_VER)
extern char **environ;
#endif
@@ -58,6 +58,8 @@ _sync(Efl_Core_Env *obj, Efl_Core_Proc_Env_Data *pd)
char **values;
values = eina_str_split(*p, "=", 2);
+ if (!values) break;
+
efl_core_env_set(obj, values[0], values[1]);
EINA_LIST_FOREACH(existing_keys, n, key)
@@ -68,6 +70,8 @@ _sync(Efl_Core_Env *obj, Efl_Core_Proc_Env_Data *pd)
break;
}
}
+ free(values[0]);
+ free(values);
}
}
EINA_LIST_FOREACH(existing_keys, n, key)
diff --git a/src/lib/ecore/efl_cubic_bezier_interpolator.eo b/src/lib/ecore/efl_cubic_bezier_interpolator.eo
index 4c67204783..02de6741d3 100644
--- a/src/lib/ecore/efl_cubic_bezier_interpolator.eo
+++ b/src/lib/ecore/efl_cubic_bezier_interpolator.eo
@@ -1,3 +1,5 @@
+import eina_types;
+
class Efl.Cubic_Bezier_Interpolator extends Efl.Object implements Efl.Interpolator
{
[[Cubic Bezier interpolator. It starts slow, then moves quickly and then slows down
diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c
index 8609dbfac5..7239bcdf6f 100644
--- a/src/lib/ecore/efl_exe.c
+++ b/src/lib/ecore/efl_exe.c
@@ -25,8 +25,10 @@
# include <sys/socket.h>
# ifdef HAVE_PRCTL
# include <sys/prctl.h>
+# elif defined(HAVE_PROCCTL)
+# include <sys/procctl.h>
# endif
-# ifdef HAVE_SYS_WAIT_H
+#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
# endif
# ifndef HAVE_CLEARENV
@@ -67,6 +69,7 @@ struct _Efl_Exe_Data
} fd;
#endif
Eina_Bool exit_called : 1;
+ Eina_Bool exit_signalled : 1;
Eina_Bool run : 1;
};
@@ -150,7 +153,13 @@ _exec(const char *cmd, Efl_Exe_Flags flags, Efl_Task_Flags task_flags)
# ifdef HAVE_PRCTL
if (task_flags & EFL_TASK_FLAGS_EXIT_WITH_PARENT)
prctl(PR_SET_PDEATHSIG, SIGTERM);
-# endif
+#elif defined(HAVE_PROCCTL)
+ if (task_flags & EFL_TASK_FLAGS_EXIT_WITH_PARENT)
+ {
+ int sig = SIGTERM;
+ procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig);
+ }
+#endif
if (flags & EFL_EXE_FLAGS_GROUP_LEADER) setsid();
if (use_sh) // We have to use a shell to run this.
@@ -261,10 +270,10 @@ _efl_exe_signal(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd, Efl_Exe_Signal sig)
switch (sig)
{
- case EFL_EXE_SIGNAL_INT: s = SIGINT; break;
- case EFL_EXE_SIGNAL_QUIT: s = SIGQUIT; break;
- case EFL_EXE_SIGNAL_TERM: s = SIGTERM; break;
- case EFL_EXE_SIGNAL_KILL: s = SIGKILL; break;
+ case EFL_EXE_SIGNAL_INT: s = SIGINT; pd->exit_signalled = EINA_TRUE; break;
+ case EFL_EXE_SIGNAL_QUIT: s = SIGQUIT; pd->exit_signalled = EINA_TRUE; break;
+ case EFL_EXE_SIGNAL_TERM: s = SIGTERM; pd->exit_signalled = EINA_TRUE; break;
+ case EFL_EXE_SIGNAL_KILL: s = SIGKILL; pd->exit_signalled = EINA_TRUE; break;
case EFL_EXE_SIGNAL_CONT: s = SIGCONT; break;
case EFL_EXE_SIGNAL_STOP: s = SIGSTOP; break;
case EFL_EXE_SIGNAL_HUP: s = SIGHUP; break;
@@ -348,8 +357,10 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
return EINA_FALSE;
#else
Eo *loop;
- Efl_Task_Data *tdl, *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
+ Efl_Task_Data *tdl = NULL, *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
+ Eina_Iterator *itr = NULL, *itr2 = NULL;
const char *cmd;
+ char **newenv, **env = NULL, **e;
int devnull;
int pipe_stdin[2];
int pipe_stdout[2];
@@ -419,9 +430,57 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
}
_ecore_signal_pid_lock();
+ // get these before the fork to avoid heap malloc deadlocks
+ loop = efl_provider_find(obj, EFL_LOOP_CLASS);
+ if (loop) tdl = efl_data_scope_get(loop, EFL_TASK_CLASS);
+ if (pd->env) itr = efl_core_env_content_get(pd->env);
+ if (pd->env) itr2 = efl_core_env_content_get(pd->env);
+ sigset_t newset, oldset;
+
+ sigemptyset(&newset);
+ sigaddset(&newset, SIGPIPE);
+ sigaddset(&newset, SIGALRM);
+ sigaddset(&newset, SIGCHLD);
+ sigaddset(&newset, SIGUSR1);
+ sigaddset(&newset, SIGUSR2);
+ sigaddset(&newset, SIGHUP);
+ sigaddset(&newset, SIGQUIT);
+ sigaddset(&newset, SIGINT);
+ sigaddset(&newset, SIGTERM);
+ sigaddset(&newset, SIGBUS);
+ sigaddset(&newset, SIGCONT);
+ sigaddset(&newset, SIGWINCH);
+# ifdef SIGEMT
+ sigaddset(&newset, SIGEMT);
+# endif
+# ifdef SIGIO
+ sigaddset(&newset, SIGIO);
+# endif
+# ifdef SIGTSTP
+ sigaddset(&newset, SIGTSTP);
+# endif
+# ifdef SIGTTIN
+ sigaddset(&newset, SIGTTIN);
+# endif
+# ifdef SIGTTOU
+ sigaddset(&newset, SIGTTOU);
+# endif
+# ifdef SIGVTALRM
+ sigaddset(&newset, SIGVTALRM);
+# endif
+# ifdef SIGPWR
+ sigaddset(&newset, SIGPWR);
+# endif
+ // block all those nasty signals we don't want messing with things
+ // in signal handlers while we go from fork to exec in the child
+ pthread_sigmask(SIG_BLOCK, &newset, &oldset);
pd->pid = fork();
+
if (pd->pid != 0)
{
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ if (itr) eina_iterator_free(itr);
+ if (itr2) eina_iterator_free(itr2);
// parent process is here inside this if block
if (td->flags & EFL_TASK_FLAGS_USE_STDIN) close(pipe_stdin[0]);
if (td->flags & EFL_TASK_FLAGS_USE_STDOUT) close(pipe_stdout[1]);
@@ -446,6 +505,13 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
pd->run = EINA_TRUE;
return EINA_TRUE;
}
+ struct sigaction sa;
+ int sig;
+
+ sa.sa_handler = SIG_DFL;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ for (sig = 0; sig < 32; sig++) sigaction(sig, &sa, NULL);
// this code is in the child here, and is temporary setup until we
// exec() the child to replace everything.
@@ -471,13 +537,14 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
{
// hide stdin
devnull = open("/dev/null", O_RDONLY);
- dup2(devnull, STDIN_FILENO);
+ if (devnull < 0) _exit(1);
+ if (dup2(devnull, STDIN_FILENO) < 0) _exit(1);
close(devnull);
}
else if ((td->flags & EFL_TASK_FLAGS_USE_STDIN))
{
// hook up stdin to the pipe going to the parent
- dup2(pipe_stdin[0], STDIN_FILENO);
+ if (dup2(pipe_stdin[0], STDIN_FILENO) < 0) _exit(1);
close(pipe_stdin[0]);
}
@@ -486,13 +553,14 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
{
// hide stdout
devnull = open("/dev/null", O_WRONLY);
- dup2(devnull, STDOUT_FILENO);
+ if (devnull < 0) _exit(1);
+ if (dup2(devnull, STDOUT_FILENO) < 0) _exit(1);
close(devnull);
}
else if ((td->flags & EFL_TASK_FLAGS_USE_STDOUT))
{
// hook up stdout to the pipe going to the parent
- dup2(pipe_stdout[1], STDOUT_FILENO);
+ if (dup2(pipe_stdout[1], STDOUT_FILENO) < 0) _exit(1);
close(pipe_stdout[1]);
}
@@ -500,58 +568,90 @@ _efl_exe_efl_task_run(Eo *obj, Efl_Exe_Data *pd)
{
// hide stderr
devnull = open("/dev/null", O_WRONLY);
- dup2(devnull, STDERR_FILENO);
+ if (devnull < 0) _exit(1);
+ if (dup2(devnull, STDERR_FILENO) < 0) _exit(1);
close(devnull);
}
- if (!(loop = efl_provider_find(obj, EFL_LOOP_CLASS))) exit(1);
-
- if (!(tdl = efl_data_scope_get(loop, EFL_TASK_CLASS))) exit(1);
+ if (!tdl) _exit(1);
// clear systemd notify socket... only relevant for systemd world,
// otherwise shouldn't be trouble
- putenv("NOTIFY_SOCKET=");
+# if defined (__FreeBSD__) || defined (__OpenBSD__)
+ _dl_environ = dlsym(NULL, "environ");
+ if (_dl_environ) env = *_dl_environ;
+# else
+ env = environ;
+# endif
+ if (env)
+ {
+ Eina_Bool shuffle = EINA_FALSE;
+
+ for (e = env; *e; e++)
+ {
+ if (!shuffle)
+ {
+ if (!strncmp(e[0], "NOTIFY_SOCKET=", 14))
+ shuffle = EINA_TRUE;
+ }
+ if (shuffle) e[0] = e[1];
+ }
+ }
// actually setenv the env object (clear what was there before so it is
// the only env there)
if (pd->env)
{
- Eina_Iterator *itr;
const char *key;
+ int count = 0, i = 0;
-# ifdef HAVE_CLEARENV
- clearenv();
-# else
-# if defined (__FreeBSD__) || defined (__OpenBSD__)
- _dl_environ = dlsym(NULL, "environ");
- if (_dl_environ) *_dl_environ = NULL;
- else ERR("Can't find envrion symbol");
-# else
- environ = NULL;
-# endif
-# endif
- itr = efl_core_env_content_get(pd->env);
-
+ // use 2nd throw-away itr to count
+ EINA_ITERATOR_FOREACH(itr2, key)
+ {
+ count++;
+ }
+ // object which we don't free (sitting in hash table in env obj)
+ newenv = alloca(sizeof(char *) * (count + 1));
+ // use 2st iter to walk and fill new env
EINA_ITERATOR_FOREACH(itr, key)
{
- setenv(key, efl_core_env_get(pd->env, key) , 1);
+ newenv[i] = (char *)efl_core_env_get(pd->env, key);
+ i++;
}
- efl_unref(pd->env);
- pd->env = NULL;
+ // yes - we dont free itr or itr2 - we're going to exec below or exit
+ // also put newenv array on stack pointign to the strings in the env
+# if defined (__FreeBSD__) || defined (__OpenBSD__)
+ if (_dl_environ) *_dl_environ = newenv;
+ else ERR("Can't find envrion symbol");
+# else
+ environ = newenv;
+# endif
}
// close all fd's other than the first 3 (0, 1, 2) and exited write fd
int except[2] = { 0, -1 };
except[0] = pd->fd.exited_write;
eina_file_close_from(3, except);
-
+# ifdef HAVE_PRCTL
+ if ((pd->flags & EFL_EXE_FLAGS_TERM_WITH_PARENT))
+ {
+ prctl(PR_SET_PDEATHSIG, SIGTERM);
+ }
+# elif defined(HAVE_PROCCTL)
+ if ((pd->flags & EFL_EXE_FLAGS_TERM_WITH_PARENT))
+ {
+ int sig = SIGTERM;
+ procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &sig);
+ }
+# endif
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
// actually execute!
_exec(cmd, pd->flags, td->flags);
// we couldn't exec... uh oh. HAAAAAAAALP!
if ((errno == EACCES) || (errno == EINVAL) || (errno == ELOOP) ||
(errno == ENOEXEC) || (errno == ENOMEM))
- exit(126);
- exit(127);
+ _exit(126);
+ _exit(127);
return EINA_FALSE;
#endif
}
@@ -562,6 +662,7 @@ _efl_exe_efl_task_end(Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
#ifdef _WIN32
#else
if (pd->pid == -1) return;
+ pd->exit_signalled = EINA_TRUE;
kill(pd->pid, SIGINT);
#endif
}
@@ -572,6 +673,16 @@ _efl_exe_exit_signal_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
return pd->exit_signal;
}
+EOLIAN static int
+_efl_exe_pid_get(const Eo *obj EINA_UNUSED, Efl_Exe_Data *pd)
+{
+#ifndef _WIN32
+ if (pd->pid != -1)
+ return pd->pid;
+#endif
+ return 0;
+}
+
EOLIAN static Efl_Object *
_efl_exe_efl_object_constructor(Eo *obj, Efl_Exe_Data *pd)
{
@@ -594,7 +705,7 @@ _efl_exe_efl_object_destructor(Eo *obj, Efl_Exe_Data *pd)
{
#ifdef _WIN32
#else
- if (!pd->exit_called)
+ if ((!pd->exit_called) && (!pd->exit_signalled))
ERR("Exe being destroyed while child has not exited yet.");
if (pd->fd.exited_read >= 0)
{
diff --git a/src/lib/ecore/efl_exe.eo b/src/lib/ecore/efl_exe.eo
index 23b68935e4..c4cc2d7ebf 100644
--- a/src/lib/ecore/efl_exe.eo
+++ b/src/lib/ecore/efl_exe.eo
@@ -18,7 +18,8 @@ enum @beta Efl.Exe_Flags {
[[Flags to customize process behavior.]]
none = 0, [[No special flags.]]
group_leader = 1, [[Process will be executed in its own session.]]
- hide_io = 4 [[All console IO will be hidden.]]
+ hide_io = 4, [[All console IO will be hidden.]]
+ term_with_parent = 8, [[Makes child receive SIGTERM when parent dies.]]
}
class @beta Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Efl.Io.Closer, Efl.Core.Command_Line
@@ -51,6 +52,15 @@ class @beta Efl.Exe extends Efl.Task implements Efl.Io.Reader, Efl.Io.Writer, Ef
sig: int; [[The exit signal, or -1 if no exit signal happened.]]
}
}
+ @property pid {
+ [[The pid of the process, which is only accessible after the object has been finalized.
+ @since 1.24
+ ]]
+ get { }
+ values {
+ pid: int; [[The pid, or 0 on failure.]]
+ }
+ }
@property env {
[[If $env is $NULL then the process created by this object is
going to inherit the environment of this process.
diff --git a/src/lib/ecore/efl_filter_model.c b/src/lib/ecore/efl_filter_model.c
index cc18dca89b..4ef3316947 100644
--- a/src/lib/ecore/efl_filter_model.c
+++ b/src/lib/ecore/efl_filter_model.c
@@ -314,39 +314,6 @@ _filter_remove_array(Eo *o EINA_UNUSED, void *data, const Eina_Value v)
return eina_value_object_init(target);
}
-/* Result from eina_future_all_array is an EINA_VALUE_TYPE_ARRAY that contain Eina_Value of
- Eo Model. It is expected that children slice get return an EINA_VALUE_TYPE_ARRAY that
- contain Eo Model directly.
-*/
-static Eina_Value
-_filter_cleanup_array(Eo *o EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v)
-{
- unsigned int i, len;
- Eina_Value created = EINA_VALUE_EMPTY;
- Eina_Value r = EINA_VALUE_EMPTY;
-
- eina_value_array_setup(&r, EINA_VALUE_TYPE_OBJECT, 4);
-
- EINA_VALUE_ARRAY_FOREACH(&v, len, i, created)
- {
- Eo *target = NULL;
-
- if (eina_value_type_get(&created) != EINA_VALUE_TYPE_OBJECT)
- goto on_error;
-
- target = eina_value_object_get(&created);
- if (!target) goto on_error;
-
- eina_value_array_append(&r, target);
- }
-
- return r;
-
- on_error:
- eina_value_flush(&r);
- return eina_value_error_init(EFL_MODEL_ERROR_UNKNOWN);
-}
-
static Eina_Future *
_efl_filter_model_efl_model_children_slice_get(Eo *obj, Efl_Filter_Model_Data *pd,
unsigned int start, unsigned int count)
@@ -389,7 +356,7 @@ _efl_filter_model_efl_model_children_slice_get(Eo *obj, Efl_Filter_Model_Data *p
}
r[i] = EINA_FUTURE_SENTINEL;
- f = efl_future_then(obj, eina_future_all_array(r), .success = _filter_cleanup_array);
+ f = efl_future_then(obj, eina_future_all_array(r), .success = _efl_future_all_repack);
free(r);
free(mapping);
diff --git a/src/lib/ecore/efl_io_copier.eo b/src/lib/ecore/efl_io_copier.eo
index e172a0c41d..291bdbc0ef 100644
--- a/src/lib/ecore/efl_io_copier.eo
+++ b/src/lib/ecore/efl_io_copier.eo
@@ -148,7 +148,7 @@ class @beta Efl.Io.Copier extends Efl.Loop_Consumer implements Efl.Io.Closer {
destination then the "done" event is emitted.
If the destination is not set (ie: $NULL) then data is kept
- in a internal @Eina.Binbuf, which can be stolen with
+ in a internal binbuf, which can be stolen with
@.binbuf_steal once "data" or "line" events are
emitted. It exists as a useful shortcut to easily drain
readers and store all data in memory with no need to use an
@@ -313,7 +313,7 @@ class @beta Efl.Io.Copier extends Efl.Loop_Consumer implements Efl.Io.Closer {
which case you should wait for "done", "data" or "line"
events and then call it to retrieve and own the data.
]]
- return: ptr(Eina.Binbuf) @move @no_unused; [[Binbuf]]
+ return: binbuf @move @no_unused; [[Binbuf]]
}
@property pending_size {
diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c
index 726a4b36a0..d85d5b1661 100644
--- a/src/lib/ecore/efl_loop.c
+++ b/src/lib/ecore/efl_loop.c
@@ -140,7 +140,11 @@ efl_loop_exit_code_process(Eina_Value *value)
eina_value_setup(&v, EINA_VALUE_TYPE_INT);
if (!eina_value_convert(value, &v)) r = -1;
- else eina_value_get(&v, &r);
+ else
+ {
+ if (!eina_value_get(&v, &r))
+ r = -1;
+ }
}
else
{
diff --git a/src/lib/ecore/efl_loop_consumer.eo b/src/lib/ecore/efl_loop_consumer.eo
index e384240c0b..a028e5aff1 100644
--- a/src/lib/ecore/efl_loop_consumer.eo
+++ b/src/lib/ecore/efl_loop_consumer.eo
@@ -1,3 +1,5 @@
+import eina_types;
+
abstract Efl.Loop_Consumer extends Efl.Object
{
[[An @Efl.Loop_Consumer is a class which requires one of the parents to provide
diff --git a/src/lib/ecore/efl_loop_model.c b/src/lib/ecore/efl_loop_model.c
index d3e52a63fb..88d8574285 100644
--- a/src/lib/ecore/efl_loop_model.c
+++ b/src/lib/ecore/efl_loop_model.c
@@ -108,6 +108,42 @@ _efl_loop_model_efl_model_property_ready_get(Eo *obj, void *pd EINA_UNUSED, cons
return efl_future_then(obj, f);
}
+static Eina_Value
+_unpack_from_array(void *data EINA_UNUSED, Eina_Value v, const Eina_Future *f EINA_UNUSED)
+{
+ Eo *object = NULL;
+
+ if (eina_value_type_get(&v) == EINA_VALUE_TYPE_ERROR) return v;
+ if (eina_value_type_get(&v) != EINA_VALUE_TYPE_ARRAY) return eina_value_error_init(EINVAL);
+ if (eina_value_array_count(&v) != 1) return eina_value_error_init(EINVAL);
+
+ eina_value_array_get(&v, 0, &object);
+
+ return eina_value_object_init(object);
+}
+
+static Eina_Future *
+_efl_loop_model_efl_model_children_index_get(Eo *obj, void *pd EINA_UNUSED, Eina_Iterator *indexes)
+{
+ Eina_Future *r;
+ Eina_Array futures;
+ unsigned int idx;
+
+ eina_array_step_set(&futures, sizeof (Eina_Array), 8);
+
+ EINA_ITERATOR_FOREACH(indexes, idx)
+ eina_array_push(&futures, eina_future_then(efl_model_children_slice_get(obj, idx, 1), _unpack_from_array, NULL));
+ eina_iterator_free(indexes);
+
+ r = efl_future_then(obj, eina_future_all_iterator(eina_array_iterator_new(&futures)),
+ .success = _efl_future_all_repack,
+ .success_type = EINA_VALUE_TYPE_ARRAY);
+
+ eina_array_flush(&futures);
+
+ return r;
+}
+
static void
_noref_death(void *data EINA_UNUSED, const Efl_Event *event)
{
diff --git a/src/lib/ecore/efl_loop_model.eo b/src/lib/ecore/efl_loop_model.eo
index 2285b56f1b..06af337ecf 100644
--- a/src/lib/ecore/efl_loop_model.eo
+++ b/src/lib/ecore/efl_loop_model.eo
@@ -20,5 +20,6 @@ abstract Efl.Loop_Model extends Efl.Loop_Consumer implements Efl.Model
Efl.Object.invalidate;
Efl.Model.property_ready_get;
Efl.Model.property { get; set; }
+ Efl.Model.children_index_get;
}
}
diff --git a/src/lib/ecore/efl_thread.c b/src/lib/ecore/efl_thread.c
index ab6fdab7a1..9fc6b8d882 100644
--- a/src/lib/ecore/efl_thread.c
+++ b/src/lib/ecore/efl_thread.c
@@ -826,8 +826,8 @@ _efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
close(pd->fd.out);
close(pd->ctrl.in);
close(pd->ctrl.out);
- close(thdat->fd.in);
- close(thdat->fd.out);
+ if (thdat->fd.in >= 0) close(thdat->fd.in);
+ if (thdat->fd.out >= 0) close(thdat->fd.out);
close(thdat->ctrl.in);
close(thdat->ctrl.out);
free(thdat);
diff --git a/src/lib/ecore/efl_threadio.eo b/src/lib/ecore/efl_threadio.eo
index 58629fd7b4..80b4f5b653 100644
--- a/src/lib/ecore/efl_threadio.eo
+++ b/src/lib/ecore/efl_threadio.eo
@@ -1,5 +1,3 @@
-import efl_object;
-
function @beta EflThreadIOCall {
[[A Function to be called asynchronously on a different thread.]]
params {
diff --git a/src/lib/ecore/meson.build b/src/lib/ecore/meson.build
index 34c32e753d..dfc2dece55 100644
--- a/src/lib/ecore/meson.build
+++ b/src/lib/ecore/meson.build
@@ -1,5 +1,10 @@
-ecore_deps = [intl]
+ecore_deps = []
ecore_pub_deps = [eina, eo, efl]
+ecore_ext_deps = [intl, m, buildsystem]
+
+if sys_sun == true
+ ecore_deps += [malloc]
+endif
pub_legacy_eo_files = [
'ecore_event_message.eo',
@@ -98,7 +103,7 @@ ecore_header_src = [
'efl_loop_timer_eo.legacy.h',
]
-ecore_src = [
+ecore_src = files([
'efl_app.c',
'ecore.c',
'ecore_alloc.c',
@@ -168,18 +173,18 @@ ecore_src = [
'efl_core_env.c',
'efl_core_proc_env.c',
'efl_core_command_line.c',
-]
+])
if sys_windows == true
#nothing for now ... needs testing
- ecore_src += ['ecore_exe_win32.c']
+ ecore_src += files(['ecore_exe_win32.c'])
else
- ecore_src += ['ecore_signal.c', 'ecore_exe_posix.c']
+ ecore_src += files(['ecore_signal.c', 'ecore_exe_posix.c'])
endif
if get_option('glib') == true and sys_windows == false
- ecore_deps += dependency('glib-2.0')
- ecore_deps += dependency('gthread-2.0')
+ ecore_ext_deps += dependency('glib-2.0')
+ ecore_ext_deps += dependency('gthread-2.0')
config_h.set('GLIB_INTEGRATION_ALWAYS', '1')
config_h.set('HAVE_GLIB', '1')
endif
@@ -192,13 +197,9 @@ if get_option('g-mainloop') == true
endif
endif
-if get_option('systemd') == true
- ecore_deps += systemd
-endif
-
ecore_lib = library('ecore',
ecore_src, pub_eo_file_target,
- dependencies: ecore_pub_deps + [m, buildsystem, ecore_deps],
+ dependencies: ecore_pub_deps + [ecore_deps, ecore_ext_deps],
include_directories : config_dir + [include_directories(join_paths('..','..'))],
install: true,
c_args : package_c_args,