diff options
Diffstat (limited to 'src/lib/ecore')
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, |