1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 
5 #define EINA_SLSTR_INTERNAL
6 
7 #define FD_SETSIZE 8192
8 
9 #ifdef _WIN32
10 # ifndef USER_TIMER_MINIMUM
11 #  define USER_TIMER_MINIMUM 0x0a
12 # endif
13 #endif
14 
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <math.h>
20 #include <sys/types.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <sys/time.h>
24 
25 #ifdef HAVE_IEEEFP_H
26 # include <ieeefp.h> // for Solaris
27 #endif
28 
29 #ifdef HAVE_ISFINITE
30 # define ECORE_FINITE(t)  isfinite(t)
31 #else
32 # define ECORE_FINITE(t) finite(t)
33 #endif
34 
35 //#define FIX_HZ 1
36 
37 #ifdef FIX_HZ
38 # include <sys/param.h>
39 # ifndef HZ
40 #  define HZ 100
41 # endif
42 #endif
43 
44 #ifdef _WIN32
45 # include <evil_private.h> /* evil_last_error_get */
46 #endif
47 #include "Ecore.h"
48 #include "ecore_private.h"
49 
50 #include "ecore_main_common.h"
51 
52 #include "eina_internal.h"
53 
54 #ifdef USE_G_MAIN_LOOP
55 # include <glib.h>
56 #endif
57 
58 #ifdef HAVE_LIBUV
59 # ifdef HAVE_NODE_UV_H
60 #  include <node/uv.h>
61 # elif defined(HAVE_NODEJS_DEPS_UV_UV_H)
62 #  include <nodejs/deps/uv/uv.h>
63 # elif defined(HAVE_NODEJS_DEPS_UV_INCLUDE_UV_H)
64 #  include <nodejs/deps/uv/include/uv.h>
65 # elif defined(HAVE_NODEJS_SRC_UV_H)
66 #  include <nodejs/src/uv.h>
67 # elif defined(HAVE_UV_H)
68 #  include <uv.h>
69 # else
70 #  error No uv.h header found?
71 # endif
72 
73 // XXX: FIXME: use eina_module
74 # if defined(HAVE_DLOPEN) && !defined(_WIN32)
75 #  include <dlfcn.h>
76 # endif
77 
78 static uv_prepare_t _ecore_main_uv_prepare;
79 static uv_check_t _ecore_main_uv_check;
80 static uv_timer_t _ecore_main_uv_handle_timers;
81 static Eina_Bool _ecore_main_uv_idling;
82 
83 static int (*_dl_uv_loop_alive)(uv_loop_t*) = 0;
84 static int (*_dl_uv_run)(uv_loop_t*, uv_run_mode mode) = 0;
85 static int (*_dl_uv_stop)(uv_loop_t*) = 0;
86 static uv_loop_t* (*_dl_uv_default_loop)() = 0;
87 static int (*_dl_uv_poll_init_socket)(uv_loop_t* loop, uv_poll_t* handle, uv_os_sock_t fd) = 0;
88 static int (*_dl_uv_poll_init)(uv_loop_t* loop, uv_poll_t* handle, int fd) = 0;
89 static int (*_dl_uv_poll_start)(uv_poll_t* handle, int events, uv_poll_cb cb) = 0;
90 static int (*_dl_uv_poll_stop)(uv_poll_t* handle) = 0;
91 static int (*_dl_uv_timer_init)(uv_loop_t*, uv_timer_t* handle);
92 static int (*_dl_uv_timer_start)(uv_timer_t* handle,
93                                  uv_timer_cb cb,
94                                  uint64_t timeout,
95                                  uint64_t repeat);
96 static int (*_dl_uv_timer_stop)(uv_timer_t* handle);
97 static int (*_dl_uv_prepare_init)(uv_loop_t*, uv_prepare_t* prepare);
98 static int (*_dl_uv_prepare_start)(uv_prepare_t* prepare, uv_prepare_cb cb);
99 static int (*_dl_uv_prepare_stop)(uv_prepare_t* prepare);
100 static int (*_dl_uv_check_init)(uv_loop_t*, uv_check_t* prepare);
101 static int (*_dl_uv_check_start)(uv_check_t* prepare, uv_check_cb cb);
102 static int (*_dl_uv_check_stop)(uv_check_t* prepare);
103 static int (*_dl_uv_close)(uv_handle_t* handle, uv_close_cb close_cb);
104 #endif
105 
106 #define NS_PER_SEC (1000000000.0)
107 
108 struct _Ecore_Fd_Handler
109 {
110    EINA_INLIST;
111    ECORE_MAGIC;
112    Ecore_Fd_Handler       *next_ready;
113    int                     fd;
114    Ecore_Fd_Handler_Flags  flags;
115    Eo                     *handler;
116    Eo                     *loop;
117    Efl_Loop_Data          *loop_data;
118    Ecore_Fd_Cb             func;
119    void                   *data;
120    Ecore_Fd_Cb             buf_func;
121    void                   *buf_data;
122    Ecore_Fd_Prep_Cb        prep_func;
123    void                   *prep_data;
124    int                     references;
125 #if defined(USE_G_MAIN_LOOP)
126    GPollFD                 gfd;
127 #endif
128 #ifdef HAVE_LIBUV
129    uv_poll_t               uv_handle;
130 #endif
131    Eina_Bool               read_active : 1;
132    Eina_Bool               write_active : 1;
133    Eina_Bool               error_active : 1;
134    Eina_Bool               delete_me : 1;
135    Eina_Bool               file : 1;
136    Eina_Bool               legacy : 1;
137 };
138 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Fd_Handler);
139 
140 #ifdef _WIN32
141 struct _Ecore_Win32_Handler
142 {
143    EINA_INLIST;
144    ECORE_MAGIC;
145    HANDLE                  h;
146    Eo                     *handler;
147    Eo                     *loop;
148    Efl_Loop_Data          *loop_data;
149    Ecore_Win32_Handle_Cb   func;
150    void                   *data;
151    int                     references;
152    Eina_Bool               delete_me : 1;
153 };
154 GENERIC_ALLOC_SIZE_DECLARE(Ecore_Win32_Handler);
155 #endif
156 
157 #if !defined(USE_G_MAIN_LOOP) && !defined(HAVE_LIBUV)
158 static int  _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout);
159 #endif
160 static void _ecore_main_prepare_handlers(Eo *obj, Efl_Loop_Data *pd);
161 static void _ecore_main_fd_handlers_cleanup(Eo *obj, Efl_Loop_Data *pd);
162 #ifndef _WIN32
163 # ifndef USE_G_MAIN_LOOP
164 static void _ecore_main_fd_handlers_bads_rem(Eo *obj, Efl_Loop_Data *pd);
165 # endif
166 #endif
167 static void _ecore_main_fd_handlers_call(Eo *obj, Efl_Loop_Data *pd);
168 static int  _ecore_main_fd_handlers_buf_call(Eo *obj, Efl_Loop_Data *pd);
169 #ifndef USE_G_MAIN_LOOP
170 static void _ecore_main_loop_iterate_internal(Eo *obj, Efl_Loop_Data *pd, int once_only);
171 #endif
172 
173 #ifdef _WIN32
174 static int _ecore_main_win32_select(int             nfds,
175                                     fd_set         *readfds,
176                                     fd_set         *writefds,
177                                     fd_set         *exceptfds,
178                                     struct timeval *timeout);
179 static void _ecore_main_win32_handlers_cleanup(Eo *obj, Efl_Loop_Data *pd);
180 #endif
181 
182 static void _ecore_main_loop_setup(Eo *obj, Efl_Loop_Data *pd);
183 static void _ecore_main_loop_clear(Eo *obj, Efl_Loop_Data *pd);
184 
185 // for legacy mainloop only and not other loops
186 int in_main_loop = 0;
187 #ifndef USE_G_MAIN_LOOP
188 static double t1 = 0.0;
189 static double t2 = 0.0;
190 #endif
191 
192 #ifdef _WIN32
193 Ecore_Select_Function        main_loop_select    = _ecore_main_win32_select;
194 static Ecore_Select_Function general_loop_select = _ecore_main_win32_select;
195 #else
196 # include <sys/select.h>
197 Ecore_Select_Function        main_loop_select    = select;
198 static Ecore_Select_Function general_loop_select = select;
199 #endif
200 
201 #ifdef USE_G_MAIN_LOOP
202 static GPollFD    ecore_epoll_fd;
203 static GPollFD    ecore_timer_fd;
204 static GSource   *ecore_glib_source;
205 static guint      ecore_glib_source_id;
206 static GMainLoop *ecore_main_loop;
207 static gboolean   ecore_idling;
208 static gboolean   _ecore_glib_idle_enterer_called;
209 static gboolean   ecore_fds_ready;
210 #endif
211 
212 static double _ecore_main_loop_wakeup_time = 0.0;
213 
_ecore_main_loop_wakeup_time_get(void)214 EAPI double _ecore_main_loop_wakeup_time_get(void)
215 {
216    return _ecore_main_loop_wakeup_time;
217 }
218 
219 static inline void
_update_loop_time(Efl_Loop_Data * pd)220 _update_loop_time(Efl_Loop_Data *pd)
221 {
222    double loop_time = ecore_time_get();
223    if (loop_time > pd->loop_time)
224      pd->loop_time = loop_time;
225    _ecore_main_loop_wakeup_time = loop_time;
226 }
227 
228 #ifdef EFL_EXTRA_SANITY_CHECKS
229 static inline void
_ecore_fd_valid(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd EINA_UNUSED)230 _ecore_fd_valid(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
231 {
232 # ifdef HAVE_SYS_EPOLL_H
233    if ((pd->epoll_fd >= 0) &&
234        (fcntl(pd->epoll_fd, F_GETFD) < 0))
235      {
236         ERR("arghhh you caught me! report a backtrace to edevel!");
237 #  ifdef HAVE_PAUSE
238         pause();
239 #  else
240         sleep(60);
241 #  endif
242      }
243 # endif
244 }
245 #endif
246 
247 static inline void
_ecore_try_add_to_call_list(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,Ecore_Fd_Handler * fdh)248 _ecore_try_add_to_call_list(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd, Ecore_Fd_Handler *fdh)
249 {
250    // check if this fdh is already in the list
251    if (fdh->next_ready)
252      {
253         DBG("next_ready");
254         return;
255      }
256    if (fdh->read_active || fdh->write_active || fdh->error_active || (fdh->flags & ECORE_FD_ALWAYS))
257      {
258         DBG("added");
259         // make sure next_ready is non-null by pointing to ourselves
260         // use that to indicate this fdh is in the ready list
261         // insert at the head of the list to avoid trouble
262         fdh->next_ready = pd->fd_handlers_to_call ? pd->fd_handlers_to_call : fdh;
263         pd->fd_handlers_to_call = fdh;
264      }
265 }
266 
267 static inline void
_throttle_do(Efl_Loop_Data * pd)268 _throttle_do(Efl_Loop_Data *pd)
269 {
270    if (pd->throttle == 0) return;
271    eina_evlog("+throttle", NULL, 0.0, NULL);
272    usleep(pd->throttle);
273    eina_evlog("-throttle", NULL, 0.0, NULL);
274 }
275 
276 #ifdef HAVE_SYS_EPOLL_H
277 static inline int
_ecore_get_epoll_fd(Eo * obj,Efl_Loop_Data * pd)278 _ecore_get_epoll_fd(Eo *obj, Efl_Loop_Data *pd)
279 {
280    if (pd->epoll_pid && (pd->epoll_pid != getpid())) // forked!
281      _ecore_main_loop_clear(obj, pd);
282    if ((pd->epoll_pid == 0) && (pd->epoll_fd < 0))
283      _ecore_main_loop_setup(obj, pd);
284    return pd->epoll_fd;
285 }
286 
287 static inline int
_ecore_epoll_add(int efd,int fd,int events,void * ptr)288 _ecore_epoll_add(int   efd,
289                  int   fd,
290                  int   events,
291                  void *ptr)
292 {
293    struct epoll_event ev;
294 
295    memset(&ev, 0, sizeof (ev));
296    ev.events = events;
297    ev.data.ptr = ptr;
298    DBG("adding poll on %d %08x", fd, events);
299    return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ev);
300 }
301 
302 static inline int
_ecore_poll_events_from_fdh(Ecore_Fd_Handler * fdh)303 _ecore_poll_events_from_fdh(Ecore_Fd_Handler *fdh)
304 {
305    int events = 0;
306    if (fdh->flags & ECORE_FD_READ)  events |= EPOLLIN | EPOLLHUP;
307    if (fdh->flags & ECORE_FD_WRITE) events |= EPOLLOUT | EPOLLHUP;
308    if (fdh->flags & ECORE_FD_ERROR) events |= EPOLLERR | EPOLLPRI | EPOLLHUP;
309    return events;
310 }
311 #endif
312 
313 #ifdef USE_G_MAIN_LOOP
314 static inline int
_gfd_events_from_fdh(Ecore_Fd_Handler * fdh)315 _gfd_events_from_fdh(Ecore_Fd_Handler *fdh)
316 {
317    int events = 0;
318    if (fdh->flags & ECORE_FD_READ)  events |= G_IO_IN | G_IO_HUP;
319    if (fdh->flags & ECORE_FD_WRITE) events |= G_IO_OUT | G_IO_HUP;
320    if (fdh->flags & ECORE_FD_ERROR) events |= G_IO_ERR | G_IO_HUP;
321    return events;
322 }
323 #endif
324 
325 
326 static void
_ecore_main_pre_idle_exit(void)327 _ecore_main_pre_idle_exit(void)
328 {
329    // even if we never go idle, keep up flushing some of our freeq away
330    // on every idle exit which may happen if we even never called idlers
331    // for now an idea but dont enforce
332 //   eina_freeq_reduce(eina_freeq_main_get(), 128);
333 }
334 
335 #ifdef HAVE_LIBUV
336 static void
_ecore_main_uv_poll_cb(uv_poll_t * handle,int status,int events)337 _ecore_main_uv_poll_cb(uv_poll_t *handle, int status, int events)
338 {
339    Eo *obj = ML_OBJ;
340    Efl_Loop_Data *pd = ML_DAT;
341 
342    DBG("_ecore_main_uv_poll_cb %p status %d events %d",
343        (void *)handle->data, status, events);
344    Ecore_Fd_Handler *fdh = handle->data;
345 
346    if (_ecore_main_uv_idling)
347      {
348         DBG("not IDLE anymore");
349         _ecore_main_uv_idling = EINA_FALSE;
350         eina_file_statgen_next();
351         _ecore_main_pre_idle_exit();
352         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
353         _ecore_animator_run_reset();
354      }
355 
356   if (status)               fdh->error_active = EINA_TRUE;
357   if (events & UV_READABLE) fdh->read_active  = EINA_TRUE;
358   if (events & UV_WRITABLE) fdh->write_active = EINA_TRUE;
359 
360   if (events & UV_DISCONNECT)
361      {
362         fdh->read_active  = EINA_TRUE;
363         fdh->write_active = EINA_TRUE;
364         fdh->error_active = EINA_TRUE;
365      }
366   _ecore_try_add_to_call_list(obj, pd, fdh);
367 
368   _ecore_main_fd_handlers_call(obj, pd);
369   if (pd->fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(obj, pd);
370   _ecore_signal_received_process(obj, pd);
371   efl_loop_message_process(obj);
372   _ecore_main_fd_handlers_cleanup(obj, pd);
373   _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
374 }
375 
376 static int
_ecore_main_uv_events_from_fdh(Ecore_Fd_Handler * fdh)377 _ecore_main_uv_events_from_fdh(Ecore_Fd_Handler *fdh)
378 {
379    int events = 0;
380    if (fdh->flags & ECORE_FD_READ)  events |= UV_READABLE;
381    if (fdh->flags & ECORE_FD_WRITE) events |= UV_WRITABLE;
382    DBG("events is %d", (int)events);
383    return events;
384 }
385 #endif
386 
387 static inline int
_ecore_main_fdh_poll_add(Efl_Loop_Data * pd EINA_UNUSED,Ecore_Fd_Handler * fdh)388 _ecore_main_fdh_poll_add(Efl_Loop_Data *pd EINA_UNUSED, Ecore_Fd_Handler *fdh)
389 {
390    DBG("_ecore_main_fdh_poll_add");
391    int r = 0;
392 
393 #ifdef HAVE_SYS_EPOLL_H
394 # ifdef HAVE_LIBUV
395    if (!_dl_uv_run)
396 # endif
397      {
398         if ((!fdh->file) && (pd->epoll_fd >= 0))
399           r = _ecore_epoll_add(_ecore_get_epoll_fd(fdh->loop, pd), fdh->fd,
400                                _ecore_poll_events_from_fdh(fdh), fdh);
401      }
402 # ifdef HAVE_LIBUV
403    else
404 # endif
405 #endif
406      {
407 #ifdef HAVE_LIBUV
408         if (!fdh->file)
409           {
410              DBG("_ecore_main_fdh_poll_add libuv socket %p", fdh);
411              fdh->uv_handle.data = fdh;
412              DBG("_ecore_main_fdh_poll_add2 %p", fdh);
413              _dl_uv_poll_init_socket(_dl_uv_default_loop(),
414                                      &fdh->uv_handle, fdh->fd);
415              DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data);
416              _dl_uv_poll_start(&fdh->uv_handle,
417                                _ecore_main_uv_events_from_fdh(fdh)
418                                , _ecore_main_uv_poll_cb);
419              DBG("_ecore_main_fdh_poll_add libuv DONE");
420           }
421         else
422           {
423              DBG("_ecore_main_fdh_poll_add libuv file");
424              fdh->uv_handle.data = fdh;
425              DBG("_ecore_main_fdh_poll_add2 %p", fdh);
426              _dl_uv_poll_init(_dl_uv_default_loop(),
427                               &fdh->uv_handle, fdh->fd);
428              DBG("_ecore_main_fdh_poll_add3 %p", fdh->uv_handle.data);
429              _dl_uv_poll_start(&fdh->uv_handle,
430                                _ecore_main_uv_events_from_fdh(fdh)
431                                , _ecore_main_uv_poll_cb);
432              DBG("_ecore_main_fdh_poll_add libuv DONE");
433           }
434 #elif defined(USE_G_MAIN_LOOP)
435         fdh->gfd.fd = fdh->fd;
436         fdh->gfd.events = _gfd_events_from_fdh(fdh);
437         fdh->gfd.revents = 0;
438         DBG("adding gpoll on %d %08x", fdh->fd, fdh->gfd.events);
439         g_source_add_poll(ecore_glib_source, &fdh->gfd);
440 #endif
441      }
442    return r;
443 }
444 
445 static inline void
_ecore_main_fdh_poll_del(Efl_Loop_Data * pd,Ecore_Fd_Handler * fdh)446 _ecore_main_fdh_poll_del(Efl_Loop_Data *pd, Ecore_Fd_Handler *fdh)
447 {
448 #ifdef HAVE_SYS_EPOLL_H
449 # ifdef HAVE_LIBUV
450    if (!_dl_uv_run)
451 # endif
452      {
453         if (!pd)
454           {
455              WRN("Efl_Loop_Data is NULL!");
456              return;
457           }
458 
459         if ((!fdh->file) && (pd->epoll_fd >= 0))
460           {
461              struct epoll_event ev;
462              int efd = _ecore_get_epoll_fd(fdh->loop, pd);
463 
464              memset(&ev, 0, sizeof (ev));
465              DBG("removing poll on %d", fdh->fd);
466              // could get an EBADF if somebody closed the FD before removing
467              if ((epoll_ctl(efd, EPOLL_CTL_DEL, fdh->fd, &ev) < 0))
468                {
469                   if (errno == EBADF)
470                     {
471                        WRN("fd %d closed, can't remove from epoll - reinit!",
472                            fdh->fd);
473                        _ecore_main_loop_clear(fdh->loop, pd);
474                        _ecore_main_loop_setup(fdh->loop, pd);
475                     }
476                   else ERR("Failed to delete epoll fd %d! (errno=%d)",
477                            fdh->fd, errno);
478                }
479           }
480      }
481 # ifdef HAVE_LIBUV
482    else
483 # endif
484 #endif
485      {
486 #ifdef HAVE_LIBUV
487         DBG("_ecore_main_fdh_poll_del libuv %p", fdh);
488         uv_handle_t* h = (uv_handle_t*)&fdh->uv_handle;
489         _dl_uv_close(h, 0);
490         DBG("_ecore_main_fdh_poll_del libuv DONE");
491 #elif USE_G_MAIN_LOOP
492         fdh->gfd.fd = fdh->fd;
493         fdh->gfd.events = _gfd_events_from_fdh(fdh);
494         fdh->gfd.revents = 0;
495         DBG("removing gpoll on %d %08x", fdh->fd, fdh->gfd.events);
496         g_source_remove_poll(ecore_glib_source, &fdh->gfd);
497 #endif
498      }
499 }
500 
501 static inline int
_ecore_main_fdh_poll_modify(Efl_Loop_Data * pd EINA_UNUSED,Ecore_Fd_Handler * fdh)502 _ecore_main_fdh_poll_modify(Efl_Loop_Data *pd EINA_UNUSED, Ecore_Fd_Handler *fdh)
503 {
504    DBG("_ecore_main_fdh_poll_modify %p", fdh);
505    int r = 0;
506 #ifdef HAVE_SYS_EPOLL_H
507 # ifdef HAVE_LIBUV
508    if (!_dl_uv_run)
509 # endif
510      {
511         if ((!fdh->file) && (pd->epoll_fd >= 0))
512           {
513              struct epoll_event ev;
514              int efd = _ecore_get_epoll_fd(fdh->loop, pd);
515 
516              memset(&ev, 0, sizeof (ev));
517              ev.events = _ecore_poll_events_from_fdh(fdh);
518              ev.data.ptr = fdh;
519              DBG("modifing epoll on %d to %08x", fdh->fd, ev.events);
520              r = epoll_ctl(efd, EPOLL_CTL_MOD, fdh->fd, &ev);
521           }
522      }
523 # ifdef HAVE_LIBUV
524    else
525 # endif
526 #endif
527      {
528 #ifdef HAVE_LIBUV
529         _dl_uv_poll_start(&fdh->uv_handle, _ecore_main_uv_events_from_fdh(fdh)
530                           , _ecore_main_uv_poll_cb);
531 #elif defined(USE_G_MAIN_LOOP)
532         fdh->gfd.fd = fdh->fd;
533         fdh->gfd.events = _gfd_events_from_fdh(fdh);
534         fdh->gfd.revents = 0;
535         DBG("modifing gpoll on %d to %08x", fdh->fd, fdh->gfd.events);
536 #endif
537      }
538    return r;
539 }
540 
541 static Eina_Bool
_ecore_main_idlers_exist(Efl_Loop_Data * pd)542 _ecore_main_idlers_exist(Efl_Loop_Data *pd)
543 {
544    return pd->idlers || eina_freeq_ptr_pending(eina_freeq_main_get());
545 }
546 
547 static void
_ecore_main_idler_all_call(Eo * loop,Efl_Loop_Data * pd)548 _ecore_main_idler_all_call(Eo *loop, Efl_Loop_Data *pd)
549 {
550    if (pd->idlers)
551      efl_event_callback_call(loop, EFL_LOOP_EVENT_IDLE, NULL);
552    eina_freeq_reduce(eina_freeq_main_get(), 256);
553 }
554 
555 #ifdef HAVE_SYS_EPOLL_H
556 static inline int
_ecore_main_fdh_epoll_mark_active(Eo * obj,Efl_Loop_Data * pd)557 _ecore_main_fdh_epoll_mark_active(Eo *obj, Efl_Loop_Data *pd)
558 {
559    DBG("_ecore_main_fdh_epoll_mark_active");
560    struct epoll_event ev[32];
561    int i, ret;
562    int efd = _ecore_get_epoll_fd(obj, pd);
563 
564    memset(&ev, 0, sizeof (ev));
565    ret = epoll_wait(efd, ev, sizeof(ev) / sizeof(struct epoll_event), 0);
566    if (ret < 0)
567      {
568         if (errno == EINTR) return -1;
569         ERR("epoll_wait failed on fd: %d %s", efd, strerror(errno));
570         return -1;
571      }
572 
573    for (i = 0; i < ret; i++)
574      {
575         Ecore_Fd_Handler *fdh;
576 
577         fdh = ev[i].data.ptr;
578         if (!ECORE_MAGIC_CHECK(fdh, ECORE_MAGIC_FD_HANDLER))
579           {
580              ECORE_MAGIC_FAIL(fdh, ECORE_MAGIC_FD_HANDLER,
581                               "_ecore_main_fdh_epoll_mark_active");
582              continue;
583           }
584         if (fdh->delete_me)
585           {
586              ERR("deleted fd in epoll");
587              continue;
588           }
589 
590         if (ev[i].events & EPOLLIN)  fdh->read_active  = EINA_TRUE;
591         if (ev[i].events & EPOLLOUT) fdh->write_active = EINA_TRUE;
592         if (ev[i].events & EPOLLERR) fdh->error_active = EINA_TRUE;
593 
594         if (ev[i].events & EPOLLHUP)
595           {
596              fdh->read_active  = EINA_TRUE;
597              fdh->write_active = EINA_TRUE;
598              fdh->error_active = EINA_TRUE;
599           }
600         /* We'll add this one anyway outside this function,
601            don't want it twice */
602         if (fdh->flags & ECORE_FD_ALWAYS)
603           continue;
604 
605         _ecore_try_add_to_call_list(obj, pd, fdh);
606      }
607    return ret;
608 }
609 #endif
610 
611 #ifdef USE_G_MAIN_LOOP
612 static inline int
_ecore_main_fdh_glib_mark_active(Eo * obj,Efl_Loop_Data * pd)613 _ecore_main_fdh_glib_mark_active(Eo *obj, Efl_Loop_Data *pd)
614 {
615    Ecore_Fd_Handler *fdh;
616    int ret = 0;
617 
618    // call the prepare callback for all handlers
619    EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
620      {
621         if (fdh->delete_me) continue;
622 
623         if (fdh->gfd.revents & G_IO_IN)  fdh->read_active  = EINA_TRUE;
624         if (fdh->gfd.revents & G_IO_OUT) fdh->write_active = EINA_TRUE;
625         if (fdh->gfd.revents & G_IO_ERR) fdh->error_active = EINA_TRUE;
626 
627         if (fdh->gfd.revents & G_IO_HUP)
628           {
629              fdh->read_active  = EINA_TRUE;
630              fdh->write_active = EINA_TRUE;
631              fdh->error_active = EINA_TRUE;
632           }
633 
634         _ecore_try_add_to_call_list(obj, pd, fdh);
635 
636         if (fdh->gfd.revents & (G_IO_IN | G_IO_OUT | G_IO_ERR)) ret++;
637      }
638 
639    return ret;
640 }
641 
642 // like we are about to enter main_loop_select in  _ecore_main_select
643 static gboolean
_ecore_main_gsource_prepare(GSource * source EINA_UNUSED,gint * next_time)644 _ecore_main_gsource_prepare(GSource *source EINA_UNUSED,
645                             gint    *next_time)
646 {
647    Eo *obj = ML_OBJ;
648    Efl_Loop_Data *pd = ML_DAT;
649    gboolean ready = FALSE;
650 
651    in_main_loop++;
652    pd->in_loop = in_main_loop;
653 
654    if ((!ecore_idling) && (!_ecore_glib_idle_enterer_called))
655      {
656         _update_loop_time(pd);
657         _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
658 
659         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
660         _ecore_throttle();
661         _throttle_do(pd);
662         _ecore_glib_idle_enterer_called = FALSE;
663 
664         if (pd->fd_handlers_with_buffer)
665           _ecore_main_fd_handlers_buf_call(obj, pd);
666      }
667 
668    _ecore_signal_received_process(obj, pd);
669 
670    // don't check fds if somebody quit
671    if (g_main_loop_is_running(ecore_main_loop))
672      {
673         // only set idling state in dispatch
674         if (ecore_idling && (!_ecore_main_idlers_exist(pd)) &&
675             (!pd->message_queue))
676           {
677              if (_efl_loop_timers_exists(obj, pd))
678                {
679                   int r = -1;
680                   double t = _efl_loop_timer_next_get(obj, pd);
681 
682                   if ((pd->timer_fd >= 0) && (t > 0.0))
683                     {
684                        struct itimerspec ts;
685 
686                        ts.it_interval.tv_sec = 0;
687                        ts.it_interval.tv_nsec = 0;
688                        ts.it_value.tv_sec = t;
689                        ts.it_value.tv_nsec = fmod(t * NS_PER_SEC, NS_PER_SEC);
690 
691                        // timerfd cannot sleep for 0 time
692                        if (ts.it_value.tv_sec || ts.it_value.tv_nsec)
693                          {
694                             r = timerfd_settime(pd->timer_fd, 0, &ts, NULL);
695                             if (r < 0)
696                               {
697                                  ERR("timer set returned %d (errno=%d)",
698                                      r, errno);
699                                  close(pd->timer_fd);
700                                  pd->timer_fd = -1;
701                               }
702                             else INF("sleeping for %ld s %06ldus",
703                                      ts.it_value.tv_sec,
704                                      ts.it_value.tv_nsec / 1000);
705                          }
706                     }
707                   if (r == -1)
708                     {
709                        *next_time = ceil(t * 1000.0);
710                        if (t == 0.0) ready = TRUE;
711                     }
712                }
713              else *next_time = -1;
714           }
715         else
716           {
717              *next_time = 0;
718              if (pd->message_queue) ready = TRUE;
719           }
720 
721         if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd);
722      }
723    else ready = TRUE;
724 
725    in_main_loop--;
726    pd->in_loop = in_main_loop;
727    DBG("leave, timeout = %d", *next_time);
728 
729    // ready if we're not running (about to quit)
730    return ready;
731 }
732 
733 static gboolean
_ecore_main_gsource_check(GSource * source EINA_UNUSED)734 _ecore_main_gsource_check(GSource *source EINA_UNUSED)
735 {
736    Eo *obj = ML_OBJ;
737    Efl_Loop_Data *pd = ML_DAT;
738    gboolean ret = FALSE;
739 
740    in_main_loop++;
741    pd->in_loop = in_main_loop;
742    // check if old timers expired
743    if (ecore_idling && (!_ecore_main_idlers_exist(pd)) &&
744        (!pd->message_queue))
745      {
746         if (pd->timer_fd >= 0)
747           {
748              uint64_t count = 0;
749              int r = read(pd->timer_fd, &count, sizeof count);
750              if ((r == -1) && (errno == EAGAIN))
751                {
752                }
753              else if (r == sizeof count) ret = TRUE;
754              else
755                {
756                   // unexpected things happened... fail back to old way
757                   ERR("timer read returned %d (errno=%d)", r, errno);
758                   close(pd->timer_fd);
759                   pd->timer_fd = -1;
760                }
761           }
762      }
763    else ret = TRUE;
764 
765    // check if fds are ready
766 #ifdef HAVE_SYS_EPOLL_H
767    if (pd->epoll_fd >= 0)
768      ecore_fds_ready = (_ecore_main_fdh_epoll_mark_active(obj, pd) > 0);
769    else
770 #endif
771      ecore_fds_ready = (_ecore_main_fdh_glib_mark_active(obj, pd) > 0);
772    _ecore_main_fd_handlers_cleanup(obj, pd);
773    if (ecore_fds_ready) ret = TRUE;
774 
775    // check timers after updating loop time
776    if (!ret && _efl_loop_timers_exists(obj, pd))
777      ret = (0.0 == _efl_loop_timer_next_get(obj, pd));
778 
779    in_main_loop--;
780    pd->in_loop = in_main_loop;
781    return ret;
782 }
783 
784 // like we just came out of main_loop_select in  _ecore_main_select
785 static gboolean
_ecore_main_gsource_dispatch(GSource * source EINA_UNUSED,GSourceFunc callback EINA_UNUSED,gpointer user_data EINA_UNUSED)786 _ecore_main_gsource_dispatch(GSource    *source EINA_UNUSED,
787                              GSourceFunc callback EINA_UNUSED,
788                              gpointer    user_data EINA_UNUSED)
789 {
790    Eo *obj = ML_OBJ;
791    Efl_Loop_Data *pd = ML_DAT;
792    gboolean events_ready, timers_ready, idlers_ready;
793    double next_time;
794 
795    _update_loop_time(pd);
796    _efl_loop_timer_enable_new(obj, pd);
797    next_time = _efl_loop_timer_next_get(obj, pd);
798 
799    events_ready = pd->message_queue ? 1 : 0;
800    timers_ready = _efl_loop_timers_exists(obj, pd) && (0.0 == next_time);
801    idlers_ready = _ecore_main_idlers_exist(pd);
802 
803    in_main_loop++;
804    pd->in_loop = in_main_loop;
805    DBG("enter idling=%d fds=%d events=%d timers=%d (next=%.2f) idlers=%d",
806        ecore_idling, ecore_fds_ready, events_ready,
807        timers_ready, next_time, idlers_ready);
808 
809    if (ecore_idling && events_ready)
810      {
811         _ecore_animator_run_reset();
812         eina_file_statgen_next();
813         _ecore_main_pre_idle_exit();
814         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
815         ecore_idling = 0;
816      }
817    else if (!ecore_idling && !events_ready) ecore_idling = 1;
818 
819    if (ecore_idling)
820      {
821         _ecore_main_idler_all_call(obj, pd);
822 
823         events_ready = pd->message_queue ? 1 : 0;
824 
825         if (ecore_fds_ready || events_ready || timers_ready)
826           {
827              _ecore_animator_run_reset();
828              eina_file_statgen_next();
829              _ecore_main_pre_idle_exit();
830              efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
831              ecore_idling = 0;
832           }
833      }
834 
835    // process events
836    if (!ecore_idling)
837      {
838         _ecore_main_fd_handlers_call(obj, pd);
839         if (pd->fd_handlers_with_buffer)
840           _ecore_main_fd_handlers_buf_call(obj, pd);
841         _ecore_signal_received_process(obj, pd);
842         efl_loop_message_process(obj);
843         _ecore_main_fd_handlers_cleanup(obj, pd);
844 
845         _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
846 
847         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
848         _ecore_throttle();
849         _throttle_do(pd);
850         _ecore_glib_idle_enterer_called = TRUE;
851 
852         if (pd->fd_handlers_with_buffer)
853           _ecore_main_fd_handlers_buf_call(obj, pd);
854      }
855 
856    in_main_loop--;
857    pd->in_loop = in_main_loop;
858 
859    return TRUE; // what should be returned here?
860 }
861 
862 static void
_ecore_main_gsource_finalize(GSource * source EINA_UNUSED)863 _ecore_main_gsource_finalize(GSource *source EINA_UNUSED)
864 {
865 }
866 
867 static GSourceFuncs ecore_gsource_funcs =
868 {
869    .prepare  = _ecore_main_gsource_prepare,
870    .check    = _ecore_main_gsource_check,
871    .dispatch = _ecore_main_gsource_dispatch,
872    .finalize = _ecore_main_gsource_finalize,
873 };
874 #endif
875 
876 #ifdef HAVE_LIBUV
877 static inline void _ecore_main_loop_uv_check(uv_check_t *handle);
878 static void _ecore_main_loop_uv_prepare(uv_prepare_t *handle);
879 
880 static void
_ecore_main_loop_timer_run(uv_timer_t * timer EINA_UNUSED)881 _ecore_main_loop_timer_run(uv_timer_t *timer EINA_UNUSED)
882 {
883    Eo *obj = ML_OBJ;
884    Efl_Loop_Data *pd = ML_DAT;
885 
886    if (_ecore_main_uv_idling)
887      {
888         _ecore_main_uv_idling = EINA_FALSE;
889         eina_file_statgen_next();
890         _ecore_main_pre_idle_exit();
891         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
892         _ecore_animator_run_reset();
893      }
894    _update_loop_time(pd);
895    _ecore_main_loop_uv_check(NULL);
896    _ecore_main_loop_uv_prepare(NULL);
897 }
898 
899 static inline void
_ecore_main_loop_uv_check(uv_check_t * handle EINA_UNUSED)900 _ecore_main_loop_uv_check(uv_check_t *handle EINA_UNUSED)
901 {
902    Eo *obj = ML_OBJ;
903    Efl_Loop_Data *pd = ML_DAT;
904 
905    DBG("_ecore_main_loop_uv_check idling? %d", (int)_ecore_main_uv_idling);
906    in_main_loop++;
907    pd->in_loop = in_main_loop;
908 
909    if (pd->do_quit) goto quit;
910 
911    do
912      {
913         _ecore_main_fd_handlers_call(obj, pd);
914         if (pd->fd_handlers_with_buffer)
915           _ecore_main_fd_handlers_buf_call(obj, pd);
916         _ecore_signal_received_process(obj, pd);
917         efl_loop_message_process(obj);
918         _ecore_main_fd_handlers_cleanup(obj, pd);
919         _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
920      }
921    while (pd->fd_handlers_to_call);
922 quit:
923    in_main_loop--;
924    pd->in_loop = in_main_loop;
925 }
926 #endif
927 
928 static void
_ecore_main_loop_setup(Eo * obj,Efl_Loop_Data * pd)929 _ecore_main_loop_setup(Eo *obj, Efl_Loop_Data *pd)
930 {
931    // Please note that this function is being also called in case of a bad
932    // fd to reset the main loop.
933 #ifdef HAVE_SYS_EPOLL_H
934    pd->epoll_fd = epoll_create(1);
935    if (pd->epoll_fd < 0) WRN("Failed to create epoll fd!");
936    else
937      {
938         eina_file_close_on_exec(pd->epoll_fd, EINA_TRUE);
939 
940         pd->epoll_pid = getpid();
941 
942         // add polls on all our file descriptors
943         Ecore_Fd_Handler *fdh;
944         EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
945           {
946              if (fdh->delete_me) continue;
947              _ecore_epoll_add(pd->epoll_fd, fdh->fd,
948                               _ecore_poll_events_from_fdh(fdh), fdh);
949              _ecore_main_fdh_poll_add(pd, fdh);
950           }
951      }
952 #endif
953 
954    if (obj == ML_OBJ)
955      {
956 #ifdef HAVE_LIBUV
957         // XXX: FIXME: the below uv init should not assert but gracefully
958         // fail with errors
959         DBG("loading lib uv");
960 # ifdef HAVE_NODEJS
961         void *lib = dlopen(NULL, RTLD_LAZY);
962 # else
963         void *lib = dlopen("libuv.so.1", RTLD_GLOBAL | RTLD_LAZY);
964 # endif
965 
966         if (lib && dlsym(lib, "uv_run"))
967           {
968              DBG("loaded lib uv");
969              _dl_uv_run = dlsym(lib, "uv_run");
970              assert(!!_dl_uv_run);
971              _dl_uv_stop = dlsym(lib, "uv_stop");
972              assert(!!_dl_uv_stop);
973              _dl_uv_default_loop = dlsym(lib, "uv_default_loop");
974              assert(!!_dl_uv_default_loop);
975              _dl_uv_poll_init_socket = dlsym(lib, "uv_poll_init_socket");
976              assert(!!_dl_uv_poll_init_socket);
977              _dl_uv_poll_init = dlsym(lib, "uv_poll_init");
978              assert(!!_dl_uv_poll_init);
979              _dl_uv_poll_start = dlsym(lib, "uv_poll_start");
980              assert(!!_dl_uv_poll_start);
981              _dl_uv_poll_stop = dlsym(lib, "uv_poll_stop");
982              assert(!!_dl_uv_poll_stop);
983              _dl_uv_timer_init = dlsym(lib, "uv_timer_init");
984              assert(!!_dl_uv_timer_init);
985              _dl_uv_timer_start = dlsym(lib, "uv_timer_start");
986              assert(!!_dl_uv_timer_start);
987              _dl_uv_timer_stop = dlsym(lib, "uv_timer_stop");
988              assert(!!_dl_uv_timer_stop);
989              _dl_uv_prepare_init = dlsym(lib, "uv_prepare_init");
990              assert(!!_dl_uv_prepare_init);
991              _dl_uv_prepare_start = dlsym(lib, "uv_prepare_start");
992              assert(!!_dl_uv_prepare_start);
993              _dl_uv_prepare_stop = dlsym(lib, "uv_prepare_stop");
994              assert(!!_dl_uv_prepare_stop);
995              _dl_uv_check_init = dlsym(lib, "uv_check_init");
996              assert(!!_dl_uv_check_init);
997              _dl_uv_check_start = dlsym(lib, "uv_check_start");
998              assert(!!_dl_uv_check_start);
999              _dl_uv_check_stop = dlsym(lib, "uv_check_stop");
1000              assert(!!_dl_uv_check_stop);
1001              _dl_uv_close = dlsym(lib, "uv_close");
1002              assert(!!_dl_uv_close);
1003              _dl_uv_loop_alive = dlsym(lib, "uv_loop_alive");
1004              assert(!!_dl_uv_loop_alive);
1005 
1006              //dlclose(lib);
1007 
1008              DBG("_dl_uv_prepare_init");
1009              _dl_uv_prepare_init(_dl_uv_default_loop(), &_ecore_main_uv_prepare);
1010              DBG("_dl_uv_prepare_start");
1011              _dl_uv_prepare_start(&_ecore_main_uv_prepare, &_ecore_main_loop_uv_prepare);
1012              DBG("_dl_uv_prepare_started");
1013 
1014              DBG("_dl_uv_check_init");
1015              _dl_uv_check_init(_dl_uv_default_loop(), &_ecore_main_uv_check);
1016              DBG("_dl_uv_check_start");
1017              _dl_uv_check_start(&_ecore_main_uv_check, &_ecore_main_loop_uv_check);
1018              DBG("_dl_uv_check_started");
1019 
1020              _dl_uv_timer_init(_dl_uv_default_loop(),  &_ecore_main_uv_handle_timers);
1021           }
1022         // else
1023         //   DBG("did not load uv");
1024         DBG("loaded dlsyms uv");
1025 #endif
1026 
1027         // setup for the g_main_loop only integration
1028 #ifdef USE_G_MAIN_LOOP
1029         ecore_glib_source = g_source_new(&ecore_gsource_funcs,
1030                                          sizeof(GSource));
1031         if (!ecore_glib_source) CRI("Failed to create glib source for epoll!");
1032         else
1033           {
1034              g_source_set_priority(ecore_glib_source,
1035                                    G_PRIORITY_HIGH_IDLE + 20);
1036 # ifdef HAVE_SYS_EPOLL_H
1037              if (pd->epoll_fd >= 0)
1038                {
1039                   // epoll multiplexes fds into the g_main_loop
1040                   ecore_epoll_fd.fd = pd->epoll_fd;
1041                   ecore_epoll_fd.events = G_IO_IN;
1042                   ecore_epoll_fd.revents = 0;
1043                   g_source_add_poll(ecore_glib_source, &ecore_epoll_fd);
1044                }
1045 # endif
1046              // timerfd gives us better than millisecond accuracy
1047              pd->timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
1048              if (pd->timer_fd < 0) WRN("failed to create timer fd!");
1049              else
1050                {
1051                   eina_file_close_on_exec(pd->timer_fd, EINA_TRUE);
1052                   ecore_timer_fd.fd = pd->timer_fd;
1053                   ecore_timer_fd.events = G_IO_IN;
1054                   ecore_timer_fd.revents = 0;
1055                   g_source_add_poll(ecore_glib_source, &ecore_timer_fd);
1056                }
1057 
1058              ecore_glib_source_id = g_source_attach(ecore_glib_source, NULL);
1059              if (ecore_glib_source_id <= 0)
1060                CRI("Failed to attach glib source to default context");
1061           }
1062 #endif
1063      }
1064    _ecore_main_timechanges_start(obj);
1065 }
1066 
1067 static void
_ecore_main_loop_clear(Eo * obj,Efl_Loop_Data * pd)1068 _ecore_main_loop_clear(Eo *obj, Efl_Loop_Data *pd)
1069 {
1070    if (!pd) return;
1071    // Please note that _ecore_main_loop_shutdown is called in cycle to
1072    // restart the main loop in case of a bad fd
1073    if (obj == ML_OBJ)
1074      {
1075         _ecore_main_timechanges_stop(obj);
1076 #ifdef USE_G_MAIN_LOOP
1077         if (ecore_glib_source)
1078           {
1079              g_source_destroy(ecore_glib_source);
1080              ecore_glib_source = NULL;
1081           }
1082 #endif
1083 #ifdef HAVE_LIBUV
1084         if (_dl_uv_run)
1085           {
1086              DBG("_ecore_main_loop_shutdown");
1087              _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
1088              _dl_uv_close((uv_handle_t*)&_ecore_main_uv_handle_timers, 0);
1089           }
1090 #endif
1091      }
1092 # ifdef HAVE_SYS_EPOLL_H
1093    if (pd->epoll_fd >= 0)
1094      {
1095         close(pd->epoll_fd);
1096         pd->epoll_fd = -1;
1097      }
1098 #endif
1099    if (pd->timer_fd >= 0)
1100      {
1101         close(pd->timer_fd);
1102         pd->timer_fd = -1;
1103      }
1104 }
1105 
1106 void
_ecore_main_loop_init(void)1107 _ecore_main_loop_init(void)
1108 {
1109    DBG("_ecore_main_loop_init");
1110    if (!efl_main_loop_get()) ERR("Cannot create main loop object");
1111    _ecore_main_loop_setup(ML_OBJ, ML_DAT);
1112 }
1113 
1114 void
_ecore_main_loop_shutdown(void)1115 _ecore_main_loop_shutdown(void)
1116 {
1117    if (!ML_OBJ) return;
1118    _ecore_main_loop_clear(ML_OBJ, ML_DAT);
1119 // XXX: this seemingly closes fd's it shouldn't.... :( fd 0?
1120    efl_replace(&ML_OBJ, NULL);
1121    ML_DAT = NULL;
1122 }
1123 
1124 void
_ecore_main_loop_iterate(Eo * obj,Efl_Loop_Data * pd)1125 _ecore_main_loop_iterate(Eo *obj, Efl_Loop_Data *pd)
1126 {
1127    if (obj == ML_OBJ)
1128      {
1129 #ifdef HAVE_LIBUV
1130         if (!_dl_uv_run)
1131           {
1132 #endif
1133 #ifndef USE_G_MAIN_LOOP
1134              _update_loop_time(pd);
1135              _ecore_main_loop_iterate_internal(obj, pd, 1);
1136 #else
1137              g_main_context_iteration(NULL, 0);
1138 #endif
1139 #ifdef HAVE_LIBUV
1140           }
1141         else
1142           _dl_uv_run(_dl_uv_default_loop(), UV_RUN_ONCE | UV_RUN_NOWAIT);
1143 #endif
1144      }
1145    else
1146      {
1147 #ifndef USE_G_MAIN_LOOP
1148         _update_loop_time(pd);
1149         _ecore_main_loop_iterate_internal(obj, pd, 1);
1150 #else
1151              g_main_context_iteration(NULL, 0);
1152 #endif
1153      }
1154 }
1155 
1156 int
_ecore_main_loop_iterate_may_block(Eo * obj,Efl_Loop_Data * pd,int may_block)1157 _ecore_main_loop_iterate_may_block(Eo *obj, Efl_Loop_Data *pd, int may_block)
1158 {
1159    if (obj == ML_OBJ)
1160      {
1161 #ifdef HAVE_LIBUV
1162         if (!_dl_uv_run)
1163           {
1164 #endif
1165 #ifndef USE_G_MAIN_LOOP
1166              in_main_loop++;
1167              pd->in_loop = in_main_loop;
1168              _update_loop_time(pd);
1169              _ecore_main_loop_iterate_internal(obj, pd, !may_block);
1170              in_main_loop--;
1171              pd->in_loop = in_main_loop;
1172              return pd->message_queue ? 1 : 0;
1173 #else
1174              return g_main_context_iteration(NULL, may_block);
1175 #endif
1176 #ifdef HAVE_LIBUV
1177           }
1178         else
1179           _dl_uv_run(_dl_uv_default_loop(),
1180                      may_block ? (UV_RUN_ONCE | UV_RUN_NOWAIT) : UV_RUN_ONCE);
1181 #endif
1182      }
1183    else
1184      {
1185 #ifndef USE_G_MAIN_LOOP
1186         pd->in_loop++;
1187         _update_loop_time(pd);
1188         _ecore_main_loop_iterate_internal(obj, pd, !may_block);
1189         pd->in_loop--;
1190         return pd->message_queue ? 1 : 0;
1191 #else
1192         return g_main_context_iteration(NULL, may_block);
1193 #endif
1194      }
1195    return 0;
1196 }
1197 
1198 void
_ecore_main_loop_begin(Eo * obj,Efl_Loop_Data * pd)1199 _ecore_main_loop_begin(Eo *obj, Efl_Loop_Data *pd)
1200 {
1201    pd->loop_active++;
1202    if (obj == ML_OBJ)
1203      {
1204 #ifdef HAVE_SYSTEMD
1205         if (getenv("NOTIFY_SOCKET"))
1206           {
1207              _ecore_sd_init();
1208              if (_ecore_sd_notify) _ecore_sd_notify(0, "READY=1");
1209           }
1210 #endif
1211 #ifdef HAVE_LIBUV
1212         if (!_dl_uv_run)
1213           {
1214 #endif
1215 #ifndef USE_G_MAIN_LOOP
1216              in_main_loop++;
1217              pd->in_loop = in_main_loop;
1218              _update_loop_time(pd);
1219              while (!pd->do_quit)
1220                _ecore_main_loop_iterate_internal(obj, pd, 0);
1221              pd->do_quit = 0;
1222              in_main_loop--;
1223              pd->in_loop = in_main_loop;
1224 #else
1225              if (!pd->do_quit)
1226                {
1227                   if (!ecore_main_loop)
1228                     ecore_main_loop = g_main_loop_new(NULL, FALSE);
1229                   g_main_loop_run(ecore_main_loop);
1230                }
1231              pd->do_quit = 0;
1232 #endif
1233 #ifdef HAVE_LIBUV
1234           }
1235         else
1236           {
1237              DBG("uv_run");
1238              in_main_loop++;
1239              pd->in_loop = in_main_loop;
1240              _update_loop_time(pd);
1241              while (!pd->do_quit)
1242                _dl_uv_run(_dl_uv_default_loop(), UV_RUN_DEFAULT);
1243              in_main_loop--;
1244              pd->in_loop = in_main_loop;
1245              pd->do_quit = 0;
1246              DBG("quit");
1247           }
1248 #endif
1249      }
1250    else
1251      {
1252 #ifndef USE_G_MAIN_LOOP
1253         pd->in_loop++;
1254         _update_loop_time(pd);
1255         while (!pd->do_quit)
1256           _ecore_main_loop_iterate_internal(obj, pd, 0);
1257         pd->do_quit = 0;
1258         pd->in_loop--;
1259 #else
1260         if (!pd->do_quit)
1261           {
1262              if (!ecore_main_loop)
1263                ecore_main_loop = g_main_loop_new(NULL, 1);
1264              g_main_loop_run(ecore_main_loop);
1265           }
1266         pd->do_quit = 0;
1267 #endif
1268      }
1269    pd->loop_active--;
1270 }
1271 
1272 void
_ecore_main_loop_quit(Eo * obj,Efl_Loop_Data * pd)1273 _ecore_main_loop_quit(Eo *obj, Efl_Loop_Data *pd)
1274 {
1275    if (!pd->loop_active) return;
1276    pd->do_quit = 1;
1277    if (obj != ML_OBJ) return;
1278 #ifdef USE_G_MAIN_LOOP
1279    if (ecore_main_loop) g_main_loop_quit(ecore_main_loop);
1280 #elif defined(HAVE_LIBUV)
1281    if (_dl_uv_run) _dl_uv_stop(_dl_uv_default_loop());
1282 #endif
1283 }
1284 
1285 EAPI void
ecore_main_loop_iterate(void)1286 ecore_main_loop_iterate(void)
1287 {
1288    EINA_MAIN_LOOP_CHECK_RETURN;
1289    efl_loop_iterate(ML_OBJ);
1290 }
1291 
1292 EAPI int
ecore_main_loop_iterate_may_block(int may_block)1293 ecore_main_loop_iterate_may_block(int may_block)
1294 {
1295    EINA_MAIN_LOOP_CHECK_RETURN_VAL(0);
1296    return efl_loop_iterate_may_block(ML_OBJ, may_block);
1297 }
1298 
1299 EAPI void
ecore_main_loop_begin(void)1300 ecore_main_loop_begin(void)
1301 {
1302    DBG("ecore_main_loop_begin");
1303    EINA_MAIN_LOOP_CHECK_RETURN;
1304    eina_evlog("+mainloop", NULL, 0.0, NULL);
1305    efl_loop_begin(ML_OBJ);
1306    eina_evlog("-mainloop", NULL, 0.0, NULL);
1307 }
1308 
1309 EAPI void
ecore_main_loop_quit(void)1310 ecore_main_loop_quit(void)
1311 {
1312    Eina_Value v = EINA_VALUE_EMPTY;
1313 
1314    eina_value_setup(&v, EINA_VALUE_TYPE_INT);
1315    eina_value_set(&v, 0);
1316    EINA_MAIN_LOOP_CHECK_RETURN;
1317    efl_loop_quit(ML_OBJ, v);
1318 }
1319 
1320 EAPI int
ecore_main_loop_nested_get(void)1321 ecore_main_loop_nested_get(void)
1322 {
1323    return in_main_loop;
1324 }
1325 
1326 EAPI Eina_Bool
ecore_main_loop_animator_ticked_get(void)1327 ecore_main_loop_animator_ticked_get(void)
1328 {
1329    DBG("ecore_main_loop_animator_ticked_get");
1330    return _ecore_animator_run_get();
1331 }
1332 
1333 EAPI void
ecore_main_loop_select_func_set(Ecore_Select_Function func)1334 ecore_main_loop_select_func_set(Ecore_Select_Function func)
1335 {
1336    EINA_MAIN_LOOP_CHECK_RETURN;
1337    main_loop_select = func;
1338 }
1339 
1340 EAPI Ecore_Select_Function
ecore_main_loop_select_func_get(void)1341 ecore_main_loop_select_func_get(void)
1342 {
1343    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1344    return main_loop_select;
1345 }
1346 
1347 Ecore_Fd_Handler *
_ecore_main_fd_handler_add(Eo * obj,Efl_Loop_Data * pd,Eo * handler,int fd,Ecore_Fd_Handler_Flags flags,Ecore_Fd_Cb func,const void * data,Ecore_Fd_Cb buf_func,const void * buf_data,Eina_Bool is_file)1348 _ecore_main_fd_handler_add(Eo                    *obj,
1349                            Efl_Loop_Data         *pd,
1350                            Eo                    *handler,
1351                            int                    fd,
1352                            Ecore_Fd_Handler_Flags flags,
1353                            Ecore_Fd_Cb            func,
1354                            const void            *data,
1355                            Ecore_Fd_Cb            buf_func,
1356                            const void            *buf_data,
1357                            Eina_Bool              is_file)
1358 {
1359    DBG("_ecore_main_fd_handler_add");
1360    Ecore_Fd_Handler *fdh = NULL;
1361 
1362    if ((fd < 0) || (flags == 0) || (!func)) return NULL;
1363 
1364    fdh = ecore_fd_handler_calloc(1);
1365    if (!fdh) return NULL;
1366    ECORE_MAGIC_SET(fdh, ECORE_MAGIC_FD_HANDLER);
1367    fdh->loop = obj;
1368    fdh->loop_data = pd;
1369    fdh->handler = handler;
1370    fdh->fd = fd;
1371    fdh->flags = flags;
1372    fdh->file = is_file;
1373    if (_ecore_main_fdh_poll_add(pd, fdh) < 0)
1374      {
1375         int err = errno;
1376         ERR("Failed to add poll on fd %d (errno = %d: %s)!",
1377             fd, err, strerror(err));
1378         ecore_fd_handler_mp_free(fdh);
1379         return NULL;
1380      }
1381    fdh->func = func;
1382    fdh->data = (void *)data;
1383    fdh->buf_func = buf_func;
1384    if (buf_func)
1385      pd->fd_handlers_with_buffer = eina_list_append
1386        (pd->fd_handlers_with_buffer, fdh);
1387    fdh->buf_data = (void *)buf_data;
1388    if (is_file)
1389      pd->file_fd_handlers = eina_list_append
1390        (pd->file_fd_handlers, fdh);
1391    if (fdh->flags & ECORE_FD_ALWAYS)
1392      pd->always_fd_handlers = eina_list_append
1393        (pd->always_fd_handlers, fdh);
1394    pd->fd_handlers = (Ecore_Fd_Handler *)
1395      eina_inlist_append(EINA_INLIST_GET(pd->fd_handlers),
1396                         EINA_INLIST_GET(fdh));
1397    return fdh;
1398 }
1399 
1400 void *
_ecore_main_fd_handler_del(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,Ecore_Fd_Handler * fd_handler)1401 _ecore_main_fd_handler_del(Eo *obj EINA_UNUSED,
1402                            Efl_Loop_Data *pd,
1403                            Ecore_Fd_Handler *fd_handler)
1404 {
1405    void *r = fd_handler->data;
1406 
1407    DBG("_ecore_main_fd_handler_del %p", fd_handler);
1408    if (fd_handler->delete_me)
1409      {
1410         ERR("fdh %p deleted twice", fd_handler);
1411         return NULL;
1412      }
1413 
1414    fd_handler->handler = NULL;
1415    fd_handler->delete_me = EINA_TRUE;
1416    if (pd)
1417      {
1418         _ecore_main_fdh_poll_del(pd, fd_handler);
1419         pd->fd_handlers_to_delete = eina_list_append
1420           (pd->fd_handlers_to_delete, fd_handler);
1421         if (fd_handler->prep_func && pd->fd_handlers_with_prep)
1422           pd->fd_handlers_with_prep = eina_list_remove
1423             (pd->fd_handlers_with_prep, fd_handler);
1424         if (fd_handler->buf_func && pd->fd_handlers_with_buffer)
1425           pd->fd_handlers_with_buffer = eina_list_remove
1426             (pd->fd_handlers_with_buffer, fd_handler);
1427      }
1428    else
1429      {
1430         // The main loop is dead by now, so cleanup is required.
1431         ECORE_MAGIC_SET(fd_handler, ECORE_MAGIC_NONE);
1432         ecore_fd_handler_mp_free(fd_handler);
1433      }
1434    return r;
1435 }
1436 
1437 EAPI Ecore_Fd_Handler *
ecore_main_fd_handler_add(int fd,Ecore_Fd_Handler_Flags flags,Ecore_Fd_Cb func,const void * data,Ecore_Fd_Cb buf_func,const void * buf_data)1438 ecore_main_fd_handler_add(int                    fd,
1439                           Ecore_Fd_Handler_Flags flags,
1440                           Ecore_Fd_Cb            func,
1441                           const void            *data,
1442                           Ecore_Fd_Cb            buf_func,
1443                           const void            *buf_data)
1444 {
1445    Ecore_Fd_Handler *fdh = NULL;
1446    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1447    fdh = _ecore_main_fd_handler_add(efl_main_loop_get(),
1448                                     ML_DAT, NULL, fd, flags, func, data,
1449                                     buf_func, buf_data, EINA_FALSE);
1450    if (fdh) fdh->legacy = EINA_TRUE;
1451    return fdh;
1452 }
1453 
1454 EAPI Ecore_Fd_Handler *
ecore_main_fd_handler_file_add(int fd,Ecore_Fd_Handler_Flags flags,Ecore_Fd_Cb func,const void * data,Ecore_Fd_Cb buf_func,const void * buf_data)1455 ecore_main_fd_handler_file_add(int                    fd,
1456                                Ecore_Fd_Handler_Flags flags,
1457                                Ecore_Fd_Cb            func,
1458                                const void            *data,
1459                                Ecore_Fd_Cb            buf_func,
1460                                const void            *buf_data)
1461 {
1462    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1463    return _ecore_main_fd_handler_add(efl_main_loop_get(),
1464                                      ML_DAT, NULL, fd, flags, func, data,
1465                                      buf_func, buf_data, EINA_TRUE);
1466 }
1467 
1468 EAPI void *
ecore_main_fd_handler_del(Ecore_Fd_Handler * fd_handler)1469 ecore_main_fd_handler_del(Ecore_Fd_Handler *fd_handler)
1470 {
1471    if (!fd_handler) return NULL;
1472    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1473 
1474    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1475      {
1476         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1477                          "ecore_main_fd_handler_del");
1478         return NULL;
1479      }
1480    return _ecore_main_fd_handler_del(ML_OBJ, ML_DAT, fd_handler);
1481 }
1482 
1483 #ifdef _WIN32
1484 EAPI Ecore_Win32_Handler *
_ecore_main_win32_handler_add(Eo * obj,Efl_Loop_Data * pd,Eo * handler,void * h,Ecore_Win32_Handle_Cb func,const void * data)1485 _ecore_main_win32_handler_add(Eo                    *obj,
1486                               Efl_Loop_Data         *pd,
1487                               Eo                    *handler,
1488                               void                  *h,
1489                               Ecore_Win32_Handle_Cb  func,
1490                               const void            *data)
1491 {
1492    Ecore_Win32_Handler *wh;
1493 
1494    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1495    if (!h || !func) return NULL;
1496 
1497    wh = ecore_win32_handler_calloc(1);
1498    if (!wh) return NULL;
1499    ECORE_MAGIC_SET(wh, ECORE_MAGIC_WIN32_HANDLER);
1500    wh->loop = obj;
1501    wh->loop_data = pd;
1502    wh->handler = handler;
1503    wh->h = (HANDLE)h;
1504    wh->func = func;
1505    wh->data = (void *)data;
1506    pd->win32_handlers = (Ecore_Win32_Handler *)
1507      eina_inlist_append(EINA_INLIST_GET(pd->win32_handlers),
1508                         EINA_INLIST_GET(wh));
1509    return wh;
1510 }
1511 
1512 void *
_ecore_main_win32_handler_del(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd,Ecore_Win32_Handler * win32_handler)1513 _ecore_main_win32_handler_del(Eo *obj EINA_UNUSED,
1514                               Efl_Loop_Data *pd,
1515                               Ecore_Win32_Handler *win32_handler)
1516 {
1517    if (win32_handler->delete_me)
1518      {
1519         ERR("win32 handler %p deleted twice", win32_handler);
1520         return NULL;
1521      }
1522 
1523    win32_handler->delete_me = EINA_TRUE;
1524    win32_handler->handler = NULL;
1525    pd->win32_handlers_to_delete = eina_list_append
1526      (pd->win32_handlers_to_delete, win32_handler);
1527    return win32_handler->data;
1528 }
1529 
1530 EAPI Ecore_Win32_Handler *
ecore_main_win32_handler_add(void * h,Ecore_Win32_Handle_Cb func,const void * data)1531 ecore_main_win32_handler_add(void                  *h,
1532                              Ecore_Win32_Handle_Cb  func,
1533                              const void            *data)
1534 {
1535    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1536    return _ecore_main_win32_handler_add(ML_OBJ, ML_DAT, NULL, h, func, data);
1537 }
1538 
1539 EAPI void *
ecore_main_win32_handler_del(Ecore_Win32_Handler * win32_handler)1540 ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler)
1541 {
1542    void *ret = NULL;
1543 
1544    if (!win32_handler) return NULL;
1545    EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1546    if (!ECORE_MAGIC_CHECK(win32_handler, ECORE_MAGIC_WIN32_HANDLER))
1547      {
1548         ECORE_MAGIC_FAIL(win32_handler, ECORE_MAGIC_WIN32_HANDLER,
1549                          "ecore_main_win32_handler_del");
1550         return NULL;
1551      }
1552    ret = _ecore_main_win32_handler_del(ML_OBJ, ML_DAT, win32_handler);
1553    return ret;
1554 }
1555 #else
1556 EAPI Ecore_Win32_Handler *
_ecore_main_win32_handler_add(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd EINA_UNUSED,Eo * handler EINA_UNUSED,void * h EINA_UNUSED,Ecore_Win32_Handle_Cb func EINA_UNUSED,const void * data EINA_UNUSED)1557 _ecore_main_win32_handler_add(Eo                    *obj EINA_UNUSED,
1558                               Efl_Loop_Data         *pd EINA_UNUSED,
1559                               Eo                    *handler EINA_UNUSED,
1560                               void                  *h EINA_UNUSED,
1561                               Ecore_Win32_Handle_Cb  func EINA_UNUSED,
1562                               const void            *data EINA_UNUSED)
1563 {
1564    return NULL;
1565 }
1566 
1567 void *
_ecore_main_win32_handler_del(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd EINA_UNUSED,Ecore_Win32_Handler * win32_handler EINA_UNUSED)1568 _ecore_main_win32_handler_del(Eo *obj EINA_UNUSED,
1569                               Efl_Loop_Data *pd EINA_UNUSED,
1570                               Ecore_Win32_Handler *win32_handler EINA_UNUSED)
1571 {
1572    return NULL;
1573 }
1574 
1575 EAPI Ecore_Win32_Handler *
ecore_main_win32_handler_add(void * h EINA_UNUSED,Ecore_Win32_Handle_Cb func EINA_UNUSED,const void * data EINA_UNUSED)1576 ecore_main_win32_handler_add(void                  *h EINA_UNUSED,
1577                              Ecore_Win32_Handle_Cb  func EINA_UNUSED,
1578                              const void            *data EINA_UNUSED)
1579 {
1580    return NULL;
1581 }
1582 
1583 EAPI void *
ecore_main_win32_handler_del(Ecore_Win32_Handler * win32_handler EINA_UNUSED)1584 ecore_main_win32_handler_del(Ecore_Win32_Handler *win32_handler EINA_UNUSED)
1585 {
1586    return NULL;
1587 }
1588 #endif
1589 
1590 EAPI void
ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler * fd_handler,Ecore_Fd_Prep_Cb func,const void * data)1591 ecore_main_fd_handler_prepare_callback_set(Ecore_Fd_Handler *fd_handler,
1592                                            Ecore_Fd_Prep_Cb  func,
1593                                            const void       *data)
1594 {
1595    if (!fd_handler) return;
1596    Efl_Loop_Data *pd = fd_handler->loop_data;
1597    EINA_MAIN_LOOP_CHECK_RETURN;
1598 
1599    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1600      {
1601         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1602                          "ecore_main_fd_handler_prepare_callback_set");
1603         return;
1604      }
1605    fd_handler->prep_func = func;
1606    fd_handler->prep_data = (void *)data;
1607    if ((!pd->fd_handlers_with_prep) ||
1608        (pd->fd_handlers_with_prep &&
1609         (!eina_list_data_find(pd->fd_handlers_with_prep, fd_handler))))
1610      // FIXME: THIS WILL NOT SCALE WITH LOTS OF PREP FUNCTIONS!!!
1611      pd->fd_handlers_with_prep = eina_list_append
1612        (pd->fd_handlers_with_prep, fd_handler);
1613 }
1614 
1615 EAPI int
ecore_main_fd_handler_fd_get(Ecore_Fd_Handler * fd_handler)1616 ecore_main_fd_handler_fd_get(Ecore_Fd_Handler *fd_handler)
1617 {
1618    if (!fd_handler) return -1;
1619 
1620    EINA_MAIN_LOOP_CHECK_RETURN_VAL(-1);
1621 
1622    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1623      {
1624         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1625                          "ecore_main_fd_handler_fd_get");
1626         return -1;
1627      }
1628    return fd_handler->fd;
1629 }
1630 
1631 EAPI Eina_Bool
ecore_main_fd_handler_active_get(Ecore_Fd_Handler * fd_handler,Ecore_Fd_Handler_Flags flags)1632 ecore_main_fd_handler_active_get(Ecore_Fd_Handler      *fd_handler,
1633                                  Ecore_Fd_Handler_Flags flags)
1634 {
1635    int ret = EINA_FALSE;
1636 
1637    EINA_MAIN_LOOP_CHECK_RETURN_VAL(EINA_FALSE);
1638 
1639    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1640      {
1641         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1642                          "ecore_main_fd_handler_active_get");
1643         return EINA_FALSE;
1644      }
1645    if ((flags & ECORE_FD_READ) &&  (fd_handler->read_active))  ret = EINA_TRUE;
1646    if ((flags & ECORE_FD_WRITE) && (fd_handler->write_active)) ret = EINA_TRUE;
1647    if ((flags & ECORE_FD_ERROR) && (fd_handler->error_active)) ret = EINA_TRUE;
1648    return ret;
1649 }
1650 
1651 EAPI void
ecore_main_fd_handler_active_set(Ecore_Fd_Handler * fd_handler,Ecore_Fd_Handler_Flags flags)1652 ecore_main_fd_handler_active_set(Ecore_Fd_Handler      *fd_handler,
1653                                  Ecore_Fd_Handler_Flags flags)
1654 {
1655    int ret = -1;
1656 
1657    if (!ECORE_MAGIC_CHECK(fd_handler, ECORE_MAGIC_FD_HANDLER))
1658      {
1659         ECORE_MAGIC_FAIL(fd_handler, ECORE_MAGIC_FD_HANDLER,
1660                          "ecore_main_fd_handler_active_set");
1661         return;
1662      }
1663    fd_handler->flags = flags;
1664    if (fd_handler->loop_data)
1665      ret = _ecore_main_fdh_poll_modify(fd_handler->loop_data, fd_handler);
1666    if (ret < 0)
1667      ERR("Failed to mod epoll fd %d, loop data=%p: %s!",
1668          fd_handler->fd, fd_handler->loop_data, strerror(errno));
1669 }
1670 
1671 void
_ecore_main_content_clear(Eo * obj,Efl_Loop_Data * pd)1672 _ecore_main_content_clear(Eo *obj, Efl_Loop_Data *pd)
1673 {
1674    __eina_promise_cancel_data(obj);
1675 
1676    while (pd->fd_handlers)
1677      {
1678         Ecore_Fd_Handler *fdh = pd->fd_handlers;
1679 
1680         pd->fd_handlers = (Ecore_Fd_Handler *)
1681           eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers),
1682                              EINA_INLIST_GET(fdh));
1683         if ((fdh->handler) && (fdh->legacy)) efl_del(fdh->handler);
1684         else
1685           {
1686 // XXX: can't do this because this fd handler is legacy and might
1687 // be cleaned up later in object destructors
1688 //             ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
1689 //             ecore_fd_handler_mp_free(fdh);
1690           }
1691      }
1692    if (pd->fd_handlers_with_buffer)
1693      pd->fd_handlers_with_buffer =
1694        eina_list_free(pd->fd_handlers_with_buffer);
1695    if (pd->fd_handlers_with_prep)
1696      pd->fd_handlers_with_prep =
1697        eina_list_free(pd->fd_handlers_with_prep);
1698    if (pd->file_fd_handlers)
1699      pd->file_fd_handlers =
1700        eina_list_free(pd->file_fd_handlers);
1701    if (pd->always_fd_handlers)
1702      pd->always_fd_handlers =
1703        eina_list_free(pd->always_fd_handlers);
1704    if (pd->fd_handlers_to_delete)
1705      pd->fd_handlers_to_delete =
1706        eina_list_free(pd->fd_handlers_to_delete);
1707    pd->fd_handlers_to_call = NULL;
1708    pd->fd_handlers_to_call_current = NULL;
1709 
1710    pd->do_quit = 0;
1711 
1712 #ifdef _WIN32
1713    while (pd->win32_handlers)
1714      {
1715         Ecore_Win32_Handler *wh = pd->win32_handlers;
1716 
1717         pd->win32_handlers = (Ecore_Win32_Handler *)
1718           eina_inlist_remove(EINA_INLIST_GET(pd->win32_handlers),
1719                              EINA_INLIST_GET(wh));
1720         if (wh->handler) efl_del(wh->handler);
1721         else
1722           {
1723              ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
1724              ecore_win32_handler_mp_free(wh);
1725           }
1726      }
1727    if (pd->win32_handlers_to_delete)
1728      pd->win32_handlers_to_delete =
1729        eina_list_free(pd->win32_handlers_to_delete);
1730    pd->win32_handler_current = NULL;
1731 #endif
1732 }
1733 
1734 void
_ecore_main_shutdown(void)1735 _ecore_main_shutdown(void)
1736 {
1737    Efl_Loop_Data *pd = ML_DAT;
1738 
1739    if (pd->in_loop)
1740      {
1741         ERR("Calling ecore_shutdown() while still in the main loop!!!");
1742         return;
1743      }
1744 }
1745 
1746 static void
_ecore_main_prepare_handlers(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)1747 _ecore_main_prepare_handlers(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
1748 {
1749    Ecore_Fd_Handler *fdh;
1750    Eina_List *l, *l2;
1751 
1752    // call the prepare callback for all handlers with prep functions
1753    EINA_LIST_FOREACH_SAFE(pd->fd_handlers_with_prep, l, l2, fdh)
1754      {
1755         if (!fdh)
1756           {
1757              pd->fd_handlers_with_prep = eina_list_remove_list
1758                (l, pd->fd_handlers_with_prep);
1759              continue;
1760           }
1761         if (!fdh->delete_me && fdh->prep_func)
1762           {
1763              fdh->references++;
1764              _ecore_call_prep_cb(fdh->prep_func, fdh->prep_data, fdh);
1765              fdh->references--;
1766           }
1767         else
1768           pd->fd_handlers_with_prep = eina_list_remove_list
1769             (pd->fd_handlers_with_prep, l);
1770      }
1771 }
1772 
1773 #if !defined(USE_G_MAIN_LOOP)
1774 static int
_ecore_main_select(Eo * obj,Efl_Loop_Data * pd,double timeout)1775 _ecore_main_select(Eo *obj, Efl_Loop_Data *pd, double timeout)
1776 {
1777    struct timeval tv, *t;
1778    fd_set rfds, wfds, exfds;
1779    Ecore_Fd_Handler *fdh;
1780    Eina_List *l;
1781    int max_fd, ret, outval;
1782 #ifndef _WIN32
1783    int err_no;
1784 #endif
1785 
1786    t = NULL;
1787    if ((!ECORE_FINITE(timeout)) || (EINA_DBL_EQ(timeout, 0.0)))
1788      { // finite() tests for NaN, too big, too small, and infinity.
1789         tv.tv_sec = 0;
1790         tv.tv_usec = 0;
1791         t = &tv;
1792      }
1793    else if (timeout > 0.0)
1794      {
1795         int sec, usec;
1796 
1797 #ifdef FIX_HZ
1798         timeout += (0.5 / HZ);
1799         sec = (int)timeout;
1800         usec = (int)((timeout - (double)sec) * 1000000);
1801 #else
1802         sec = (int)timeout;
1803         usec = (int)((timeout - (double)sec) * 1000000);
1804 #endif
1805         tv.tv_sec = sec;
1806         tv.tv_usec = usec;
1807         t = &tv;
1808      }
1809    max_fd = 0;
1810    FD_ZERO(&rfds);
1811    FD_ZERO(&wfds);
1812    FD_ZERO(&exfds);
1813 
1814    // call the prepare callback for all handlers
1815    if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd);
1816 
1817 #ifdef HAVE_SYS_EPOLL_H
1818    if (pd->epoll_fd < 0)
1819      {
1820 #endif
1821         EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
1822           {
1823              if (!fdh->delete_me)
1824                {
1825                   if ((fdh->flags & ECORE_FD_READ) || (fdh->flags & ECORE_FD_ALWAYS))
1826                     {
1827                        FD_SET(fdh->fd, &rfds);
1828                        if (fdh->fd > max_fd) max_fd = fdh->fd;
1829                     }
1830                   if ((fdh->flags & ECORE_FD_WRITE) || (fdh->flags & ECORE_FD_ALWAYS))
1831                     {
1832                        FD_SET(fdh->fd, &wfds);
1833                        if (fdh->fd > max_fd) max_fd = fdh->fd;
1834                     }
1835                   if ((fdh->flags & ECORE_FD_ERROR) || (fdh->flags & ECORE_FD_ALWAYS))
1836                     {
1837                        FD_SET(fdh->fd, &exfds);
1838                        if (fdh->fd > max_fd) max_fd = fdh->fd;
1839                     }
1840                }
1841           }
1842 #ifdef HAVE_SYS_EPOLL_H
1843      }
1844    else
1845      {
1846         // polling on the epoll fd will wake when fd in the epoll set is active
1847         max_fd = _ecore_get_epoll_fd(obj, pd);
1848         if (max_fd > -1)
1849           FD_SET(max_fd, &rfds);
1850      }
1851 #endif
1852    EINA_LIST_FOREACH(pd->file_fd_handlers, l, fdh)
1853      {
1854         if (!fdh->delete_me)
1855           {
1856              if ((fdh->flags & ECORE_FD_READ) || (fdh->flags & ECORE_FD_ALWAYS))
1857                {
1858                   FD_SET(fdh->fd, &rfds);
1859                   if (fdh->fd > max_fd) max_fd = fdh->fd;
1860                }
1861              if ((fdh->flags & ECORE_FD_WRITE) || (fdh->flags & ECORE_FD_ALWAYS))
1862                {
1863                   FD_SET(fdh->fd, &wfds);
1864                   if (fdh->fd > max_fd) max_fd = fdh->fd;
1865                }
1866              if ((fdh->flags & ECORE_FD_ERROR) || (fdh->flags & ECORE_FD_ALWAYS))
1867                {
1868                   FD_SET(fdh->fd, &exfds);
1869                   if (fdh->fd > max_fd) max_fd = fdh->fd;
1870                }
1871              if (fdh->fd > max_fd) max_fd = fdh->fd;
1872           }
1873      }
1874    if (_ecore_signal_count_get(obj, pd)) return -1;
1875 
1876    eina_evlog("<RUN", NULL, 0.0, NULL);
1877    eina_evlog("!SLEEP", NULL, 0.0, t ? "timeout" : "forever");
1878    if (obj == ML_OBJ)
1879      ret = main_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t);
1880    else
1881      ret = general_loop_select(max_fd + 1, &rfds, &wfds, &exfds, t);
1882 #ifndef _WIN32
1883    err_no = errno;
1884 #endif
1885    eina_evlog("!WAKE", NULL, 0.0, NULL);
1886    eina_evlog(">RUN", NULL, 0.0, NULL);
1887 
1888    _update_loop_time(pd);
1889    if (ret < 0)
1890      {
1891 #ifndef _WIN32
1892         if (err_no == EINTR)
1893           {
1894              outval = -1;
1895              goto BAIL;
1896           }
1897         else if (err_no == EBADF) _ecore_main_fd_handlers_bads_rem(obj, pd);
1898 #endif
1899      }
1900    if (ret > 0)
1901      {
1902 #ifdef HAVE_SYS_EPOLL_H
1903         if (pd->epoll_fd >= 0)
1904           _ecore_main_fdh_epoll_mark_active(obj, pd);
1905         else
1906 #endif
1907           {
1908              EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
1909                {
1910                   if (!fdh->delete_me)
1911                     {
1912                        if (FD_ISSET(fdh->fd, &rfds))
1913                          fdh->read_active  = EINA_TRUE;
1914                        if (FD_ISSET(fdh->fd, &wfds))
1915                          fdh->write_active = EINA_TRUE;
1916                        if (FD_ISSET(fdh->fd, &exfds))
1917                          fdh->error_active = EINA_TRUE;
1918                        _ecore_try_add_to_call_list(obj, pd, fdh);
1919                     }
1920                }
1921           }
1922         EINA_LIST_FOREACH(pd->file_fd_handlers, l, fdh)
1923           {
1924              if (!fdh->delete_me)
1925                {
1926                   if (FD_ISSET(fdh->fd, &rfds))
1927                     fdh->read_active  = EINA_TRUE;
1928                   if (FD_ISSET(fdh->fd, &wfds))
1929                     fdh->write_active = EINA_TRUE;
1930                   if (FD_ISSET(fdh->fd, &exfds))
1931                     fdh->error_active = EINA_TRUE;
1932                   _ecore_try_add_to_call_list(obj, pd, fdh);
1933                }
1934           }
1935         outval = 1;
1936         goto BAIL;
1937      }
1938    outval = 0;
1939 BAIL:
1940    EINA_LIST_FOREACH(pd->always_fd_handlers, l, fdh)
1941      _ecore_try_add_to_call_list(obj, pd, fdh);
1942 
1943    if (ret > 0)
1944      {
1945         _ecore_main_fd_handlers_cleanup(obj, pd);
1946 #ifdef _WIN32
1947         _ecore_main_win32_handlers_cleanup(obj, pd);
1948 #endif
1949      }
1950    return outval || pd->always_fd_handlers;
1951 }
1952 
1953 #endif
1954 
1955 #ifndef _WIN32
1956 # ifndef USE_G_MAIN_LOOP
1957 static void
_ecore_main_fd_handlers_bads_rem(Eo * obj,Efl_Loop_Data * pd)1958 _ecore_main_fd_handlers_bads_rem(Eo *obj, Efl_Loop_Data *pd)
1959 {
1960    Ecore_Fd_Handler *fdh;
1961    Eina_Inlist *l;
1962    int found = 0;
1963 
1964    ERR("Removing bad fds");
1965    for (l = EINA_INLIST_GET(pd->fd_handlers); l; )
1966      {
1967         fdh = (Ecore_Fd_Handler *)l;
1968         l = l->next;
1969         errno = 0;
1970 
1971         if ((fcntl(fdh->fd, F_GETFD) < 0) && (errno == EBADF))
1972           {
1973              ERR("Found bad fd at index %d", fdh->fd);
1974              if (fdh->flags & ECORE_FD_ERROR)
1975                {
1976                   ERR("Fd set for error! calling user");
1977                   fdh->references++;
1978                   if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh))
1979                     {
1980                        ERR("Fd function err returned 0, remove it");
1981                        if (!fdh->delete_me)
1982                          {
1983                             fdh->delete_me = EINA_TRUE;
1984                             _ecore_main_fdh_poll_del(pd, fdh);
1985                             pd->fd_handlers_to_delete =
1986                               eina_list_append(pd->fd_handlers_to_delete, fdh);
1987                          }
1988                        found++;
1989                     }
1990                   fdh->references--;
1991                }
1992              else
1993                {
1994                   ERR("Problematic fd found at %d! setting it for delete",
1995                       fdh->fd);
1996                   if (!fdh->delete_me)
1997                     {
1998                        fdh->delete_me = EINA_TRUE;
1999                        _ecore_main_fdh_poll_del(pd, fdh);
2000                        pd->fd_handlers_to_delete =
2001                          eina_list_append(pd->fd_handlers_to_delete, fdh);
2002                     }
2003 
2004                   found++;
2005                }
2006           }
2007      }
2008    if (found == 0)
2009      {
2010 #  ifdef HAVE_GLIB
2011         ERR("No bad fd found. Maybe a foreign fd from glib?");
2012 #  else
2013         ERR("No bad fd found. EEEK!");
2014 #  endif
2015      }
2016    _ecore_main_fd_handlers_cleanup(obj, pd);
2017 }
2018 
2019 # endif
2020 #endif
2021 
2022 static void
_ecore_main_fd_handlers_cleanup(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)2023 _ecore_main_fd_handlers_cleanup(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
2024 {
2025    Ecore_Fd_Handler *fdh, *last;
2026    Eina_List *l, *l2;
2027 
2028    // Cleanup deleted caller from the list
2029    last = NULL;
2030    fdh = pd->fd_handlers_to_call;
2031    while (fdh)
2032      {
2033         if (fdh->delete_me)
2034           {
2035              if (!last)
2036                pd->fd_handlers_to_call = fdh == fdh->next_ready ?
2037                  NULL : fdh->next_ready;
2038              else
2039                last->next_ready = fdh == fdh->next_ready ?
2040                  last : fdh->next_ready;
2041           }
2042         else last = fdh;
2043 
2044         if (fdh == fdh->next_ready) break;
2045         fdh = fdh->next_ready;
2046      }
2047 
2048    if (!pd->fd_handlers_to_delete) return;
2049    EINA_LIST_FOREACH_SAFE(pd->fd_handlers_to_delete, l, l2, fdh)
2050      {
2051         if (!fdh)
2052           {
2053              pd->fd_handlers_to_delete = eina_list_remove_list
2054                (l, pd->fd_handlers_to_delete);
2055              continue;
2056           }
2057         if (fdh->references) continue;
2058         if (pd->fd_handlers_to_call_current == fdh)
2059           pd->fd_handlers_to_call_current = NULL;
2060         if (fdh->buf_func && pd->fd_handlers_with_buffer)
2061           pd->fd_handlers_with_buffer = eina_list_remove
2062             (pd->fd_handlers_with_buffer, fdh);
2063         if (fdh->prep_func && pd->fd_handlers_with_prep)
2064           pd->fd_handlers_with_prep = eina_list_remove
2065            (pd->fd_handlers_with_prep, fdh);
2066         pd->fd_handlers = (Ecore_Fd_Handler *)
2067           eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers),
2068                              EINA_INLIST_GET(fdh));
2069         if (fdh->file)
2070           pd->file_fd_handlers = eina_list_remove(pd->file_fd_handlers, fdh);
2071         if (fdh->flags & ECORE_FD_ALWAYS)
2072           pd->always_fd_handlers = eina_list_remove(pd->always_fd_handlers, fdh);
2073         ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
2074         ecore_fd_handler_mp_free(fdh);
2075         pd->fd_handlers_to_delete = eina_list_remove_list
2076           (pd->fd_handlers_to_delete, l);
2077      }
2078 }
2079 
2080 #ifdef _WIN32
2081 static void
_ecore_main_win32_handlers_cleanup(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)2082 _ecore_main_win32_handlers_cleanup(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
2083 {
2084    Ecore_Win32_Handler *wh;
2085    Eina_List *l, *l2;
2086 
2087    if (!pd->win32_handlers_to_delete) return;
2088    EINA_LIST_FOREACH_SAFE(pd->win32_handlers_to_delete, l, l2, wh)
2089      {
2090         if (!wh)
2091           {
2092              pd->win32_handlers_to_delete = eina_list_remove_list
2093                (l, pd->win32_handlers_to_delete);
2094              continue;
2095           }
2096         // wh->delete_me should be set for all whs at the start of the list
2097         if (wh->references) continue;
2098         pd->win32_handlers = (Ecore_Win32_Handler *)
2099           eina_inlist_remove(EINA_INLIST_GET(pd->win32_handlers),
2100                              EINA_INLIST_GET(wh));
2101         ECORE_MAGIC_SET(wh, ECORE_MAGIC_NONE);
2102         ecore_win32_handler_mp_free(wh);
2103         pd->win32_handlers_to_delete = eina_list_remove_list
2104           (pd->win32_handlers_to_delete, l);
2105      }
2106 }
2107 #endif
2108 
2109 static void
_ecore_main_fd_handlers_call(Eo * obj EINA_UNUSED,Efl_Loop_Data * pd)2110 _ecore_main_fd_handlers_call(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd)
2111 {
2112    // grab a new list
2113    if (!pd->fd_handlers_to_call_current)
2114      {
2115         pd->fd_handlers_to_call_current = pd->fd_handlers_to_call;
2116         pd->fd_handlers_to_call = NULL;
2117      }
2118 
2119    if (!pd->fd_handlers_to_call_current) return;
2120    eina_evlog("+fd_handlers", NULL, 0.0, NULL);
2121 
2122    while (pd->fd_handlers_to_call_current)
2123      {
2124         Ecore_Fd_Handler *fdh = pd->fd_handlers_to_call_current;
2125 
2126         if (!fdh->delete_me)
2127           {
2128              if ((fdh->read_active) ||
2129                  (fdh->write_active) ||
2130                  (fdh->error_active) ||
2131                  (fdh->flags & ECORE_FD_ALWAYS))
2132                {
2133                   fdh->references++;
2134                   if (!_ecore_call_fd_cb(fdh->func, fdh->data, fdh))
2135                     {
2136                        if (!fdh->delete_me)
2137                          {
2138                             fdh->delete_me = EINA_TRUE;
2139                             _ecore_main_fdh_poll_del(pd, fdh);
2140                             pd->fd_handlers_to_delete = eina_list_append
2141                               (pd->fd_handlers_to_delete, fdh);
2142                          }
2143                     }
2144                   fdh->references--;
2145 #ifdef EFL_EXTRA_SANITY_CHECKS
2146                   _ecore_fd_valid(obj, pd);
2147 #endif
2148                   fdh->read_active  = EINA_FALSE;
2149                   fdh->write_active = EINA_FALSE;
2150                   fdh->error_active = EINA_FALSE;
2151                }
2152           }
2153 
2154         // stop when we point to ourselves
2155         if (fdh->next_ready == fdh)
2156           {
2157              fdh->next_ready = NULL;
2158              pd->fd_handlers_to_call_current = NULL;
2159              break;
2160           }
2161 
2162         pd->fd_handlers_to_call_current = fdh->next_ready;
2163         fdh->next_ready = NULL;
2164       }
2165    eina_evlog("-fd_handlers", NULL, 0.0, NULL);
2166 }
2167 
2168 static int
_ecore_main_fd_handlers_buf_call(Eo * obj,Efl_Loop_Data * pd)2169 _ecore_main_fd_handlers_buf_call(Eo *obj, Efl_Loop_Data *pd)
2170 {
2171    Ecore_Fd_Handler *fdh;
2172    Eina_List *l, *l2;
2173    int ret;
2174 
2175    if (!pd->fd_handlers_with_buffer) return 0;
2176    eina_evlog("+fd_handlers_buf", NULL, 0.0, NULL);
2177    ret = 0;
2178    EINA_LIST_FOREACH_SAFE(pd->fd_handlers_with_buffer, l, l2, fdh)
2179      {
2180         if (!fdh)
2181           {
2182              pd->fd_handlers_with_buffer = eina_list_remove_list
2183                (l, pd->fd_handlers_with_buffer);
2184              continue;
2185           }
2186         if ((!fdh->delete_me) && fdh->buf_func)
2187           {
2188              fdh->references++;
2189              if (_ecore_call_fd_cb(fdh->buf_func, fdh->buf_data, fdh))
2190                {
2191                   ret |= _ecore_call_fd_cb(fdh->func, fdh->data, fdh);
2192                   fdh->read_active = EINA_TRUE;
2193                   _ecore_try_add_to_call_list(obj, pd, fdh);
2194                }
2195              fdh->references--;
2196           }
2197         else
2198           pd->fd_handlers_with_buffer = eina_list_remove_list
2199             (pd->fd_handlers_with_buffer, l);
2200      }
2201    eina_evlog("-fd_handlers_buf", NULL, 0.0, NULL);
2202    return ret;
2203 }
2204 
2205 #ifdef HAVE_LIBUV
2206 static void
_ecore_main_loop_uv_prepare(uv_prepare_t * handle EINA_UNUSED)2207 _ecore_main_loop_uv_prepare(uv_prepare_t *handle EINA_UNUSED)
2208 {
2209    Eo *obj = ML_OBJ;
2210    Efl_Loop_Data *pd = ML_DAT;
2211    double t = -1;
2212 
2213    _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
2214    if ((pd->in_loop == 0) && (pd->do_quit))
2215      {
2216         _ecore_main_fd_handlers_cleanup(obj, pd);
2217 
2218         while (pd->fd_handlers)
2219           {
2220              Ecore_Fd_Handler *fdh = pd->fd_handlers;
2221              pd->fd_handlers = (Ecore_Fd_Handler *)
2222                eina_inlist_remove(EINA_INLIST_GET(pd->fd_handlers),
2223                                   EINA_INLIST_GET(fdh));
2224              fdh->delete_me = 1;
2225              _ecore_main_fdh_poll_del(pd, fdh);
2226              ECORE_MAGIC_SET(fdh, ECORE_MAGIC_NONE);
2227              ecore_fd_handler_mp_free(fdh);
2228           }
2229        if (pd->fd_handlers_with_buffer)
2230          pd->fd_handlers_with_buffer = eina_list_free(pd->fd_handlers_with_buffer);
2231        if (pd->fd_handlers_with_prep)
2232          pd->fd_handlers_with_prep = eina_list_free(pd->fd_handlers_with_prep);
2233        if (pd->fd_handlers_to_delete)
2234          pd->fd_handlers_to_delete = eina_list_free(pd->fd_handlers_to_delete);
2235        if (pd->file_fd_handlers)
2236          pd->file_fd_handlers = eina_list_free(pd->file_fd_handlers);
2237 
2238         pd->fd_handlers_to_call = NULL;
2239         pd->fd_handlers_to_call_current = NULL;
2240 
2241         _dl_uv_prepare_stop(&_ecore_main_uv_prepare);
2242         _dl_uv_check_stop(&_ecore_main_uv_check);
2243         _dl_uv_stop(_dl_uv_default_loop());
2244 
2245         return;
2246      }
2247 
2248    in_main_loop++;
2249    pd->in_loop = in_main_loop;
2250 
2251    if (!_ecore_main_uv_idling)
2252      {
2253         _ecore_main_uv_idling = EINA_TRUE;
2254         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2255         _ecore_throttle();
2256         _throttle_do(pd);
2257      }
2258 
2259    if (_ecore_main_uv_idling)
2260      {
2261         _ecore_main_idler_all_call(obj, pd);
2262         DBG("called idles");
2263         if (_ecore_main_idlers_exist(pd) || (pd->message_queue)) t = 0.0;
2264      }
2265 
2266    if (pd->do_quit)
2267      {
2268         DBG("do quit outside loop");
2269 
2270         if (_ecore_main_uv_idling)
2271           {
2272              eina_file_statgen_next();
2273              _ecore_main_pre_idle_exit();
2274              efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
2275              _ecore_animator_run_reset();
2276              _ecore_main_uv_idling = EINA_FALSE;
2277           }
2278         t = -1;
2279         _update_loop_time(pd);
2280         _efl_loop_timer_enable_new(obj, pd);
2281         goto done;
2282      }
2283 
2284    assert(!pd->fd_handlers_to_call);
2285 
2286    _update_loop_time(pd);
2287    _efl_loop_timer_enable_new(obj, pd);
2288    if (_efl_loop_timers_exists(obj, pd) || (t >= 0))
2289      {
2290         double tnext = _efl_loop_timer_next_get(obj, pd);
2291 
2292         if ((t < 0) || ((tnext >= 0) && (tnext < t))) t = tnext;
2293         DBG("Should awake after %f", t);
2294 
2295         if (t >= 0.0)
2296           {
2297              // _dl_uv_timer_stop(&_ecore_main_uv_handle_timers);
2298              _dl_uv_timer_start(&_ecore_main_uv_handle_timers,
2299                                 &_ecore_main_loop_timer_run,
2300                                 t * 1000, 0);
2301           }
2302         else DBG("Is not going to awake with timer");
2303      }
2304    else DBG("Is not going to awake with timer");
2305 
2306 done:
2307    if (pd->fd_handlers_with_prep) _ecore_main_prepare_handlers(obj, pd);
2308    in_main_loop--;
2309    pd->in_loop = in_main_loop;
2310 }
2311 #endif
2312 
2313 #if !defined(USE_G_MAIN_LOOP)
2314 enum {
2315    SPIN_MORE,
2316    SPIN_RESTART,
2317    LOOP_CONTINUE
2318 };
2319 
2320 static int
_ecore_main_loop_spin_core(Eo * obj,Efl_Loop_Data * pd)2321 _ecore_main_loop_spin_core(Eo *obj, Efl_Loop_Data *pd)
2322 {
2323    // as we are spinning we need to update loop time per spin
2324    _update_loop_time(pd);
2325    // call all idlers
2326    _ecore_main_idler_all_call(obj, pd);
2327    // which returns false if no more idelrs exist
2328    if (!_ecore_main_idlers_exist(pd)) return SPIN_RESTART;
2329    // sneaky - drop through or if checks - the first one to succeed
2330    // drops through and returns "continue" so further ones dont run
2331    if ((_ecore_main_select(obj, pd, 0.0) > 0) || (pd->message_queue) ||
2332        (_ecore_signal_count_get(obj, pd) > 0) || (pd->do_quit))
2333      return LOOP_CONTINUE;
2334    // default - spin more
2335    return SPIN_MORE;
2336 }
2337 
2338 static int
_ecore_main_loop_spin_no_timers(Eo * obj,Efl_Loop_Data * pd)2339 _ecore_main_loop_spin_no_timers(Eo *obj, Efl_Loop_Data *pd)
2340 {
2341    // if we have idlers we HAVE to spin and handle everything
2342    // in a polling way - spin in a tight polling loop
2343    for (;;)
2344      {
2345         int action = _ecore_main_loop_spin_core(obj, pd);
2346         if (action != SPIN_MORE) return action;
2347         // if an idler has added a timer then we need to go through
2348         // the start of the spin cycle again to handle cases properly
2349         if (_efl_loop_timers_exists(obj, pd)) return SPIN_RESTART;
2350      }
2351    // just contiune handling events etc.
2352    return LOOP_CONTINUE;
2353 }
2354 
2355 static int
_ecore_main_loop_spin_timers(Eo * obj,Efl_Loop_Data * pd)2356 _ecore_main_loop_spin_timers(Eo *obj, Efl_Loop_Data *pd)
2357 {
2358    // if we have idlers we HAVE to spin and handle everything
2359    // in a polling way - spin in a tight polling loop
2360    for (;;)
2361      {
2362         int action = _ecore_main_loop_spin_core(obj, pd);
2363         if (action != SPIN_MORE) return action;
2364         // if next timer expires now or in the past - stop spinning and
2365         // continue the mainloop walk as our "select" timeout has
2366         // expired now
2367         if (_efl_loop_timer_next_get(obj, pd) <= 0.0) return LOOP_CONTINUE;
2368      }
2369    // just contiune handling events etc.
2370    return LOOP_CONTINUE;
2371 }
2372 
2373 static void
_ecore_fps_marker_1(void)2374 _ecore_fps_marker_1(void)
2375 {
2376    if (!_ecore_fps_debug) return;
2377    t2 = ecore_time_get();
2378    if ((t1 > 0.0) && (t2 > 0.0)) _ecore_fps_debug_runtime_add(t2 - t1);
2379 }
2380 
2381 static void
_ecore_fps_marker_2(void)2382 _ecore_fps_marker_2(void)
2383 {
2384    if (!_ecore_fps_debug) return;
2385    t1 = ecore_time_get();
2386 }
2387 
2388 static void
_ecore_main_loop_iterate_internal(Eo * obj,Efl_Loop_Data * pd,int once_only)2389 _ecore_main_loop_iterate_internal(Eo *obj, Efl_Loop_Data *pd, int once_only)
2390 {
2391    double next_time = -1.0;
2392 
2393    if (obj == ML_OBJ)
2394      {
2395         in_main_loop++;
2396         pd->in_loop = in_main_loop;
2397      }
2398    // expire any timers
2399    _efl_loop_timer_expired_timers_call(obj, pd, pd->loop_time);
2400    // process signals into events ....
2401    if (obj == ML_OBJ) _ecore_signal_received_process(obj, pd);
2402    // if as a result of timers/animators or signals we have accumulated
2403    // events, then instantly handle them
2404    if (pd->message_queue)
2405      {
2406         // but first conceptually enter an idle state
2407         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2408         _ecore_throttle();
2409         _throttle_do(pd);
2410         // now quickly poll to see which input fd's are active
2411         _ecore_main_select(obj, pd, 0.0);
2412         // allow newly queued timers to expire from now on
2413         _efl_loop_timer_enable_new(obj, pd);
2414         // go straight to processing the events we had queued
2415         goto process_all;
2416      }
2417 
2418    if (once_only)
2419      {
2420         // in once_only mode we should quickly poll for inputs, signals
2421         // if we got any events or signals, allow new timers to process.
2422         // use bitwise or to force both conditions to be tested and
2423         // merged together
2424         if (_ecore_main_select(obj, pd, 0.0) |
2425             _ecore_signal_count_get(obj, pd))
2426           {
2427              _efl_loop_timer_enable_new(obj, pd);
2428              goto process_all;
2429           }
2430      }
2431    else
2432      {
2433         // call idle enterers ...
2434         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2435         _ecore_throttle();
2436         _throttle_do(pd);
2437      }
2438 
2439    // if these calls caused any buffered events to appear - deal with them
2440    if (pd->fd_handlers_with_buffer)
2441      _ecore_main_fd_handlers_buf_call(obj, pd);
2442 
2443    // if there are any (buffered fd handling may generate them)
2444    // then jump to processing them */
2445    if (pd->message_queue)
2446      {
2447         _ecore_main_select(obj, pd, 0.0);
2448         _efl_loop_timer_enable_new(obj, pd);
2449         goto process_all;
2450      }
2451 
2452    if (once_only)
2453      {
2454         // in once_only mode enter idle here instead and then return
2455         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2456         _ecore_throttle();
2457         _throttle_do(pd);
2458         _efl_loop_timer_enable_new(obj, pd);
2459         goto done;
2460      }
2461 
2462    if (obj == ML_OBJ) _ecore_fps_marker_1();
2463 
2464    // start of the sleeping or looping section
2465 start_loop: //-*************************************************************
2466    // any timers re-added as a result of these are allowed to go
2467    _efl_loop_timer_enable_new(obj, pd);
2468    // if we have been asked to quit the mainloop then exit at this point
2469    if (pd->do_quit)
2470      {
2471         _efl_loop_timer_enable_new(obj, pd);
2472         goto done;
2473      }
2474    if (!pd->message_queue)
2475      {
2476         // init flags
2477         next_time = _efl_loop_timer_next_get(obj, pd);
2478         // no idlers
2479         if (!_ecore_main_idlers_exist(pd))
2480           {
2481              // sleep until timeout or forever (-1.0) waiting for on fds
2482              _ecore_main_select(obj, pd, next_time);
2483           }
2484         else
2485           {
2486              int action = LOOP_CONTINUE;
2487 
2488              // no timers - spin
2489              if (next_time < 0) action = _ecore_main_loop_spin_no_timers(obj, pd);
2490              // timers - spin
2491              else action = _ecore_main_loop_spin_timers(obj, pd);
2492              if (action == SPIN_RESTART) goto start_loop;
2493           }
2494      }
2495    if (obj == ML_OBJ) _ecore_fps_marker_2();
2496 
2497    // actually wake up and deal with input, events etc.
2498 process_all: //-*********************************************************
2499 
2500    // we came out of our "wait state" so idle has exited
2501    if (!once_only)
2502      {
2503         _ecore_animator_run_reset(); // XXX:
2504         eina_file_statgen_next();
2505         _ecore_main_pre_idle_exit();
2506         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_EXIT, NULL);
2507      }
2508    // call the fd handler per fd that became alive...
2509    // this should read or write any data to the monitored fd and then
2510    // post events onto the ecore event pipe if necessary
2511    _ecore_main_fd_handlers_call(obj, pd);
2512    if (pd->fd_handlers_with_buffer) _ecore_main_fd_handlers_buf_call(obj, pd);
2513    // process signals into events ....
2514    _ecore_signal_received_process(obj, pd);
2515    // handle events ...
2516    efl_loop_message_process(obj);
2517    _ecore_main_fd_handlers_cleanup(obj, pd);
2518 
2519    if (once_only)
2520      {
2521         // if in once_only mode handle idle exiting
2522         efl_event_callback_call(obj, EFL_LOOP_EVENT_IDLE_ENTER, NULL);
2523         _ecore_throttle();
2524         _throttle_do(pd);
2525      }
2526 
2527 done: //-*****************************************************************
2528    // Agressively flush animator
2529    _ecore_animator_flush();
2530    if (!once_only)
2531      eina_slstr_local_clear(); // Free all short lived strings
2532 
2533    if (obj == ML_OBJ)
2534      {
2535         in_main_loop--;
2536         pd->in_loop = in_main_loop;
2537      }
2538 }
2539 
2540 #endif
2541 
2542 #ifdef _WIN32
2543 typedef struct
2544 {
2545    DWORD   objects_nbr;
2546    HANDLE *objects;
2547    DWORD   timeout;
2548 } Ecore_Main_Win32_Thread_Data;
2549 
2550 static unsigned int __stdcall
_ecore_main_win32_objects_wait_thread(void * data)2551 _ecore_main_win32_objects_wait_thread(void *data)
2552 {
2553    Ecore_Main_Win32_Thread_Data *td = (Ecore_Main_Win32_Thread_Data *)data;
2554    return MsgWaitForMultipleObjects(td->objects_nbr,
2555                                     (const HANDLE *)td->objects,
2556                                     FALSE,
2557                                     td->timeout,
2558                                     QS_ALLINPUT);
2559 }
2560 
2561 static DWORD
_ecore_main_win32_objects_wait(DWORD objects_nbr,const HANDLE * objects,DWORD timeout)2562 _ecore_main_win32_objects_wait(DWORD objects_nbr,
2563                                const HANDLE *objects,
2564                                DWORD timeout)
2565 {
2566    Ecore_Main_Win32_Thread_Data *threads_data;
2567    HANDLE *threads_handles;
2568    DWORD threads_nbr, threads_remain, objects_idx, result, i;
2569 
2570    if (objects_nbr < MAXIMUM_WAIT_OBJECTS)
2571      return MsgWaitForMultipleObjects(objects_nbr,
2572                                       objects,
2573                                       EINA_FALSE,
2574                                       timeout, QS_ALLINPUT);
2575    // too much objects, so we launch a bunch of threads to
2576    // wait for, each one calls MsgWaitForMultipleObjects
2577 
2578    threads_nbr = objects_nbr / (MAXIMUM_WAIT_OBJECTS - 1);
2579    threads_remain = objects_nbr % (MAXIMUM_WAIT_OBJECTS - 1);
2580    if (threads_remain > 0) threads_nbr++;
2581 
2582    if (threads_nbr > MAXIMUM_WAIT_OBJECTS)
2583      {
2584         CRI("Too much objects to wait for (%lu).", objects_nbr);
2585         return WAIT_FAILED;
2586      }
2587 
2588    threads_handles = (HANDLE *)malloc(threads_nbr * sizeof(HANDLE));
2589    if (!threads_handles)
2590      {
2591         ERR("Can not allocate memory for the waiting thread.");
2592         return WAIT_FAILED;
2593      }
2594 
2595    threads_data = (Ecore_Main_Win32_Thread_Data *)
2596      malloc(threads_nbr * sizeof(Ecore_Main_Win32_Thread_Data));
2597    if (!threads_data)
2598      {
2599         ERR("Can not allocate memory for the waiting thread.");
2600         goto free_threads_handles;
2601      }
2602 
2603    objects_idx = 0;
2604    for (i = 0; i < threads_nbr; i++)
2605      {
2606         threads_data[i].timeout = timeout;
2607         threads_data[i].objects = (HANDLE *)objects + objects_idx;
2608 
2609         if ((i == (threads_nbr - 1)) && (threads_remain != 0))
2610           {
2611              threads_data[i].objects_nbr = threads_remain;
2612              objects_idx += threads_remain;
2613           }
2614         else
2615           {
2616              threads_data[i].objects_nbr = (MAXIMUM_WAIT_OBJECTS - 1);
2617              objects_idx += (MAXIMUM_WAIT_OBJECTS - 1);
2618           }
2619 
2620         threads_handles[i] = (HANDLE)_beginthreadex
2621           (NULL, 0, _ecore_main_win32_objects_wait_thread,
2622            &threads_data[i], 0, NULL);
2623         if (!threads_handles[i])
2624           {
2625              DWORD j;
2626 
2627              ERR("Can not create the waiting threads.");
2628              WaitForMultipleObjects(i, threads_handles, TRUE, INFINITE);
2629              for (j = 0; j < i; j++)
2630                CloseHandle(threads_handles[i]);
2631 
2632              goto free_threads_data;
2633           }
2634      }
2635 
2636    result = WaitForMultipleObjects(threads_nbr,
2637                                    threads_handles,
2638                                    FALSE, // we wait until one thread signaled
2639                                    INFINITE);
2640 
2641    if (result < (WAIT_OBJECT_0 + threads_nbr))
2642      {
2643         DWORD wait_res;
2644 
2645         // One of the thread callback has exited so we retrieve
2646         // its exit status, that is the returned value of
2647         // MsgWaitForMultipleObjects()
2648         if (GetExitCodeThread(threads_handles[result - WAIT_OBJECT_0],
2649                               &wait_res))
2650           {
2651              WaitForMultipleObjects(threads_nbr, threads_handles,
2652                                     TRUE, INFINITE);
2653              for (i = 0; i < threads_nbr; i++)
2654                CloseHandle(threads_handles[i]);
2655              free(threads_data);
2656              free(threads_handles);
2657              return wait_res;
2658           }
2659      }
2660    else
2661      {
2662         ERR("Error when waiting threads.");
2663         if (result == WAIT_FAILED)
2664           ERR("%s", evil_last_error_get());
2665         goto close_thread;
2666      }
2667 
2668 close_thread:
2669    WaitForMultipleObjects(threads_nbr, threads_handles, TRUE, INFINITE);
2670    for (i = 0; i < threads_nbr; i++) CloseHandle(threads_handles[i]);
2671 free_threads_data:
2672    free(threads_data);
2673 free_threads_handles:
2674    free(threads_handles);
2675 
2676    return WAIT_FAILED;
2677 }
2678 
2679 static unsigned int
_stdin_wait_thread(void * data EINA_UNUSED)2680 _stdin_wait_thread(void *data EINA_UNUSED)
2681 {
2682    int c = getc(stdin);
2683    ungetc(c, stdin);
2684    return 0;
2685 }
2686 
2687 static int
_ecore_main_win32_select(int nfds EINA_UNUSED,fd_set * readfds,fd_set * writefds,fd_set * exceptfds,struct timeval * tv)2688 _ecore_main_win32_select(int             nfds EINA_UNUSED,
2689                          fd_set         *readfds,
2690                          fd_set         *writefds,
2691                          fd_set         *exceptfds,
2692                          struct timeval *tv)
2693 {
2694    Efl_Loop_Data *pd = ML_DAT;
2695    HANDLE *objects;
2696    int *sockets;
2697    Ecore_Fd_Handler *fdh;
2698    Ecore_Win32_Handler *wh;
2699    static HANDLE stdin_wait_thread = INVALID_HANDLE_VALUE;
2700    HANDLE stdin_handle;
2701    DWORD result, timeout;
2702    MSG msg;
2703    unsigned int fds_nbr = 0;
2704    unsigned int objects_nbr = 0;
2705    unsigned int events_nbr = 0;
2706    unsigned int i;
2707    int res;
2708    Eina_Bool stdin_thread_done = EINA_FALSE;
2709 
2710    fds_nbr = eina_inlist_count(EINA_INLIST_GET(pd->fd_handlers));
2711    sockets = (int *)malloc(fds_nbr * sizeof(int));
2712    if (!sockets) return -1;
2713 
2714    objects = (HANDLE)malloc((fds_nbr +
2715                              eina_inlist_count
2716                              (EINA_INLIST_GET(pd->win32_handlers)))
2717                             * sizeof(HANDLE));
2718    if (!objects)
2719      {
2720         free(sockets);
2721         return -1;
2722      }
2723 
2724    // Create an event object per socket
2725    EINA_INLIST_FOREACH(pd->fd_handlers, fdh)
2726      {
2727         if (fdh->delete_me) continue;
2728 
2729         WSAEVENT event;
2730         long network_event;
2731 
2732         network_event = 0;
2733         if (readfds)
2734           {
2735              if (FD_ISSET(fdh->fd, readfds))
2736                network_event |= FD_READ | FD_CONNECT | FD_ACCEPT;
2737           }
2738         if (writefds)
2739           {
2740              if (FD_ISSET(fdh->fd, writefds))
2741                network_event |= FD_WRITE | FD_CLOSE;
2742           }
2743         if (exceptfds)
2744           {
2745              if (FD_ISSET(fdh->fd, exceptfds))
2746                network_event |= FD_OOB;
2747           }
2748 
2749         if (network_event)
2750           {
2751              event = WSACreateEvent();
2752              WSAEventSelect(fdh->fd, event, network_event);
2753              objects[objects_nbr] = event;
2754              sockets[events_nbr] = fdh->fd;
2755              events_nbr++;
2756              objects_nbr++;
2757           }
2758      }
2759    stdin_handle = GetStdHandle(STD_INPUT_HANDLE);
2760    // store the HANDLEs in the objects to wait for
2761    EINA_INLIST_FOREACH(pd->win32_handlers, wh)
2762      {
2763         if (wh->delete_me) continue;
2764 
2765         if (wh->h == stdin_handle)
2766           {
2767              if (stdin_wait_thread == INVALID_HANDLE_VALUE)
2768                stdin_wait_thread = (HANDLE)_beginthreadex(NULL,
2769                                                           0,
2770                                                           _stdin_wait_thread,
2771                                                           NULL,
2772                                                           0,
2773                                                           NULL);
2774              objects[objects_nbr] = stdin_wait_thread;
2775           }
2776         else objects[objects_nbr] = wh->h;
2777         objects_nbr++;
2778      }
2779 
2780    // Empty the queue before waiting
2781    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2782      {
2783         TranslateMessage(&msg);
2784         DispatchMessage(&msg);
2785      }
2786 
2787    // Wait for any message sent or posted to this queue
2788    // or for one of the passed handles be set to signaled.
2789    if (!tv) timeout = INFINITE;
2790    else timeout = (DWORD)((tv->tv_sec * 1000.0) + (tv->tv_usec / 1000.0));
2791 
2792    if (timeout == 0)
2793      {
2794         res = 0;
2795         goto err;
2796      }
2797 
2798    result = _ecore_main_win32_objects_wait(objects_nbr,
2799                                            (const HANDLE *)objects,
2800                                            timeout);
2801    if (readfds)   FD_ZERO(readfds);
2802    if (writefds)  FD_ZERO(writefds);
2803    if (exceptfds) FD_ZERO(exceptfds);
2804    // The result tells us the type of event we have.
2805    if (result == WAIT_FAILED)
2806      {
2807         WRN("%s", evil_last_error_get());
2808         res = -1;
2809      }
2810    else if (result == WAIT_TIMEOUT)
2811      {
2812         INF("time-out interval elapsed.");
2813         res = 0;
2814      }
2815    else if (result == (WAIT_OBJECT_0 + objects_nbr))
2816      {
2817         while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2818           {
2819              TranslateMessage(&msg);
2820              DispatchMessage(&msg);
2821           }
2822         res = 0;
2823      }
2824    else if (result < WAIT_OBJECT_0 + events_nbr)
2825      {
2826         WSANETWORKEVENTS network_event;
2827 
2828         WSAEnumNetworkEvents(sockets[result], objects[result], &network_event);
2829         if ((network_event.lNetworkEvents &
2830              (FD_READ | FD_CONNECT | FD_ACCEPT)) && readfds)
2831           FD_SET(sockets[result], readfds);
2832         if ((network_event.lNetworkEvents &
2833              (FD_WRITE | FD_CLOSE)) && writefds)
2834           FD_SET(sockets[result], writefds);
2835         if ((network_event.lNetworkEvents & FD_OOB) && exceptfds)
2836           FD_SET(sockets[result], exceptfds);
2837         res = 1;
2838      }
2839    else if ((result >= (WAIT_OBJECT_0 + events_nbr)) &&
2840             (result < (WAIT_OBJECT_0 + objects_nbr)))
2841      {
2842         if (!pd->win32_handler_current)
2843           // regular main loop, start from head
2844           pd->win32_handler_current = pd->win32_handlers;
2845         else
2846           // recursive main loop, continue from where we were
2847           pd->win32_handler_current = (Ecore_Win32_Handler *)
2848             EINA_INLIST_GET(pd->win32_handler_current)->next;
2849 
2850         if (objects[result - WAIT_OBJECT_0] == stdin_wait_thread)
2851           stdin_thread_done = EINA_TRUE;
2852 
2853         while (pd->win32_handler_current)
2854           {
2855              wh = pd->win32_handler_current;
2856 
2857              if ((objects[result - WAIT_OBJECT_0] == wh->h) ||
2858                  ((objects[result - WAIT_OBJECT_0] == stdin_wait_thread) &&
2859                   (wh->h == stdin_handle)))
2860                {
2861                   if (!wh->delete_me)
2862                     {
2863                        wh->references++;
2864                        if (!wh->func(wh->data, wh))
2865                          {
2866                             wh->delete_me = EINA_TRUE;
2867                             pd->win32_handlers_to_delete = eina_list_append
2868                               (pd->win32_handlers_to_delete, wh);
2869                          }
2870                        wh->references--;
2871                     }
2872                }
2873              if (pd->win32_handler_current)
2874                // may have changed in recursive main loops
2875                pd->win32_handler_current = (Ecore_Win32_Handler *)
2876                  EINA_INLIST_GET(pd->win32_handler_current)->next;
2877           }
2878         res = 1;
2879      }
2880    else
2881      {
2882         ERR("unknown result...\n");
2883         res = -1;
2884      }
2885 
2886 err:
2887    // Remove event objects again
2888    for (i = 0; i < events_nbr; i++) WSACloseEvent(objects[i]);
2889 
2890    if (stdin_thread_done) stdin_wait_thread = INVALID_HANDLE_VALUE;
2891 
2892    free(objects);
2893    free(sockets);
2894    return res;
2895 }
2896 #endif
2897