On Sat, Jan 6, 2018 at 2:23 PM, Gustavo Sverzut Barbieri <barbi...@gmail.com
> wrote:

> for linux would you please change to
> http://man7.org/linux/man-pages/man2/signalfd.2.html


no, not for linux, for systems supporting that function

that is, add a check in configure.ac

Vincent



>
>
> On Sat, Jan 6, 2018 at 7:51 AM, Carsten Haitzler <ras...@rasterman.com>
> wrote:
> > raster pushed a commit to branch master.
> >
> > http://git.enlightenment.org/core/efl.git/commit/?id=
> ba16dee6b3d5f84e0184c86b64d5fe54e32b4966
> >
> > commit ba16dee6b3d5f84e0184c86b64d5fe54e32b4966
> > Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
> > Date:   Sat Jan 6 17:37:42 2018 +0900
> >
> >     ecore signal - move to using a pipe (and optional thread) tfor
> signals
> >
> >     this should remove any races in catching signals. it should also be
> >     portable. as well.
> > ---
> >  src/lib/ecore/ecore_signal.c | 811 ++++++++++++++++--------------
> -------------
> >  1 file changed, 301 insertions(+), 510 deletions(-)
> >
> > diff --git a/src/lib/ecore/ecore_signal.c b/src/lib/ecore/ecore_signal.c
> > index 3d743a21cd..e4f33de815 100644
> > --- a/src/lib/ecore/ecore_signal.c
> > +++ b/src/lib/ecore/ecore_signal.c
> > @@ -10,166 +10,175 @@
> >  #include <signal.h>
> >  #include <unistd.h>
> >  #include <assert.h>
> > +#include <fcntl.h>
> > +#include <pthread.h>
> >
> >  #include "Ecore.h"
> >  #include "ecore_private.h"
> >
> >  /* make mono happy - this is evil though... */
> >  #undef SIGPWR
> > -/* valgrind in some versions/setups uses SIGRT's... hmmm */
> >
> > -typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
> > -
> > -static void _ecore_signal_callback_set(int            sig,
> > -                                       Signal_Handler func);
> > -static void _ecore_signal_callback_ignore(int        sig,
> > -                                          siginfo_t *si,
> > -                                          void      *foo);
> > -static void _ecore_signal_callback_sigchld(int        sig,
> > -                                           siginfo_t *si,
> > -                                           void      *foo);
> > -static void _ecore_signal_callback_sigusr1(int        sig,
> > -                                           siginfo_t *si,
> > -                                           void      *foo);
> > -static void _ecore_signal_callback_sigusr2(int        sig,
> > -                                           siginfo_t *si,
> > -                                           void      *foo);
> > -static void _ecore_signal_callback_sighup(int        sig,
> > -                                          siginfo_t *si,
> > -                                          void      *foo);
> > -static void _ecore_signal_callback_sigquit(int        sig,
> > -                                           siginfo_t *si,
> > -                                           void      *foo);
> > -static void _ecore_signal_callback_sigint(int        sig,
> > -                                          siginfo_t *si,
> > -                                          void      *foo);
> > -static void _ecore_signal_callback_sigterm(int        sig,
> > -                                           siginfo_t *si,
> > -                                           void      *foo);
> > -#ifdef SIGPWR
> > -static void _ecore_signal_callback_sigpwr(int        sig,
> > -                                          siginfo_t *si,
> > -                                          void      *foo);
> > -#endif
> > +#define ECORE_SIGNAL_THREAD 1
> >
> >  static void _ecore_signal_exe_exit_delay(void *data, const Efl_Event
> *event);
> > +static void _ecore_signal_waitpid(Eina_Bool once, siginfo_t info);
> > +static void _ecore_signal_generic_free(void *data, void *event);
> >
> > -//#define MAXSIGQ 256 // 32k
> > -#define MAXSIGQ 64 // 8k
> > -
> > -static volatile sig_atomic_t sig_count     = 0;
> > -static volatile sig_atomic_t sigchld_count = 0;
> > -static volatile sig_atomic_t sigusr1_count = 0;
> > -static volatile sig_atomic_t sigusr2_count = 0;
> > -static volatile sig_atomic_t sighup_count  = 0;
> > -static volatile sig_atomic_t sigquit_count = 0;
> > -static volatile sig_atomic_t sigint_count  = 0;
> > -static volatile sig_atomic_t sigterm_count = 0;
> > -#ifdef SIGPWR
> > -static volatile sig_atomic_t sigpwr_count  = 0;
> > -#endif
> > +typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
> >
> > -static volatile siginfo_t sigchld_info[MAXSIGQ];
> > -static volatile siginfo_t sigusr1_info[MAXSIGQ];
> > -static volatile siginfo_t sigusr2_info[MAXSIGQ];
> > -static volatile siginfo_t sighup_info [MAXSIGQ];
> > -static volatile siginfo_t sigquit_info[MAXSIGQ];
> > -static volatile siginfo_t sigint_info [MAXSIGQ];
> > -static volatile siginfo_t sigterm_info[MAXSIGQ];
> > -#ifdef SIGPWR
> > -static volatile siginfo_t sigpwr_info [MAXSIGQ];
> > +#ifdef ECORE_SIGNAL_THREAD
> > +static Eina_Thread sig_thread;
> > +static Eina_Bool sig_thread_exists = EINA_FALSE;
> >  #endif
> > +static int sig_pipe[2] = { -1, -1 }; // [0] == read, [1] == write
> > +static Eo *sig_pipe_handler = NULL;
> >
> > -#if defined(SIG_ATOMIC_MAX)
> > -# if SIG_ATOMIC_MAX == INT64_MAX
> > -/* Basically FreeBSD on 64bits */
> > -#  define PRIdSIGATOMIC PRId64
> > -# elif SIG_ATOMIC_MAX == UINT64_MAX
> > -#  define PRIdSIGATOMIC PRIu64
> > -# elif SIG_ATOMIC_MAX == UINT32_MAX
> > -#  define PRIdSIGATOMIC PRIu32
> > -# else
> > -/* everybody else seems to go for int */
> > -#  define PRIdSIGATOMIC PRId32
> > -# endif
> > -#else
> > -# define PRIdSIGATOMIC "d"
> > -#endif
> > +typedef struct _Signal_Data
> > +{
> > +   int sig;
> > +   siginfo_t info;
> > +} Signal_Data;
> >
> > -void
> > -_ecore_signal_shutdown(void)
> > +static Eina_Bool
> > +_ecore_signal_pipe_read(void)
> >  {
> > -   _ecore_signal_callback_set(SIGPIPE, (Signal_Handler)SIG_DFL);
> > -   _ecore_signal_callback_set(SIGALRM, (Signal_Handler)SIG_DFL);
> > -   // XXX: consider using new clone4 features:
> > -   // http://code.qt.io/cgit/qt/qtbase.git/tree/src/3rdparty/
> forkfd/forkfd.c
> > -   // https://lkml.org/lkml/2015/3/12/1060
> > -   // https://lkml.org/lkml/2015/3/12/1044
> > -   _ecore_signal_callback_set(SIGCHLD, (Signal_Handler)SIG_DFL);
> > -   _ecore_signal_callback_set(SIGUSR1, (Signal_Handler)SIG_DFL);
> > -   _ecore_signal_callback_set(SIGUSR2, (Signal_Handler)SIG_DFL);
> > -   _ecore_signal_callback_set(SIGHUP,  (Signal_Handler)SIG_DFL);
> > -   _ecore_signal_callback_set(SIGQUIT, (Signal_Handler)SIG_DFL);
> > -   _ecore_signal_callback_set(SIGINT,  (Signal_Handler)SIG_DFL);
> > -   _ecore_signal_callback_set(SIGTERM, (Signal_Handler)SIG_DFL);
> > +   Signal_Data sdata;
> > +   int ret;
> > +
> > +   ret = read(sig_pipe[0], &sdata, sizeof(sdata));
> > +   if (ret != sizeof(sdata)) return EINA_FALSE;
> > +   switch (sdata.sig)
> > +     {
> > +      case SIGPIPE:
> > +        break;
> > +      case SIGALRM:
> > +        break;
> > +      case SIGCHLD:
> > +        _ecore_signal_waitpid(EINA_FALSE, sdata.info);
> > +        break;
> > +      case SIGUSR1:
> > +      case SIGUSR2:
> > +          {
> > +             Ecore_Event_Signal_User *e = _ecore_event_signal_user_new()
> ;
> > +             if (e)
> > +               {
> > +                  if (sdata.sig == SIGUSR1) e->number = 1;
> > +                  else e->number = 2;
> > +                  e->data = sdata.info;
> > +                  ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
> > +                                  _ecore_signal_generic_free, NULL);
> > +               }
> > +          }
> > +        break;
> > +      case SIGHUP:
> > +          {
> > +             Ecore_Event_Signal_Hup *e = _ecore_event_signal_hup_new();
> > +             if (e)
> > +               {
> > +                  e->data = sdata.info;
> > +                  ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e,
> > +                                  _ecore_signal_generic_free, NULL);
> > +               }
> > +          }
> > +        break;
> > +      case SIGQUIT:
> > +      case SIGINT:
> > +      case SIGTERM:
> > +          {
> > +             Ecore_Event_Signal_Exit *e = _ecore_event_signal_exit_new()
> ;
> > +             if (e)
> > +               {
> > +                  if (sdata.sig == SIGQUIT) e->quit = 1;
> > +                  else if (sdata.sig == SIGINT) e->interrupt = 1;
> > +                  else e->terminate = 1;
> > +                  e->data = sdata.info;
> > +                  ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
> > +                                  _ecore_signal_generic_free, NULL);
> > +               }
> > +          }
> > +        break;
> >  #ifdef SIGPWR
> > -   _ecore_signal_callback_set(SIGPWR,  (Signal_Handler)SIG_DFL);
> > -   sigpwr_count  = 0;
> > +      case SIGPWR:
> > +          {
> > +             Ecore_Event_Signal_Power *e =
> _ecore_event_signal_power_new();
> > +             if (e)
> > +               {
> > +                  e->data = sdata.info;
> > +                  ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e,
> > +                                  _ecore_signal_generic_free, NULL);
> > +               }
> > +          }
> > +        break;
> >  #endif
> > -   sigchld_count = 0;
> > -   sigusr1_count = 0;
> > -   sigusr2_count = 0;
> > -   sighup_count  = 0;
> > -   sigquit_count = 0;
> > -   sigint_count  = 0;
> > -   sigterm_count = 0;
> > -   sig_count     = 0;
> > +      default:
> > +        break;
> > +     }
> > +   return EINA_TRUE;
> >  }
> >
> > -void
> > -_ecore_signal_init(void)
> > +static void
> > +_ecore_signal_cb_read(void *data EINA_UNUSED, const Efl_Event *event
> EINA_UNUSED)
> >  {
> > -   _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback_ignore);
> > -   _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback_ignore);
> > -   _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback_sigchld);
> > -   _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback_sigusr1);
> > -   _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback_sigusr2);
> > -   _ecore_signal_callback_set(SIGHUP,  _ecore_signal_callback_sighup);
> > -   _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback_sigquit);
> > -   _ecore_signal_callback_set(SIGINT,  _ecore_signal_callback_sigint);
> > -   _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback_sigterm);
> > -#ifdef SIGPWR
> > -   _ecore_signal_callback_set(SIGPWR,  _ecore_signal_callback_sigpwr);
> > -#endif
> > +   while (_ecore_signal_pipe_read());
> >  }
> >
> > -void
> > -_ecore_signal_received_process(Eo *obj, Efl_Loop_Data *pd)
> > +static void
> > +_ecore_signal_cb_del(void *data EINA_UNUSED, const Efl_Event *event)
> >  {
> > -   while (_ecore_signal_count_get(obj, pd)) _ecore_signal_call(obj, pd);
> > +   if (event->object == sig_pipe_handler) sig_pipe_handler = NULL;
> >  }
> >
> > -int
> > -_ecore_signal_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd
> EINA_UNUSED)
> > +EFL_CALLBACKS_ARRAY_DEFINE(_event_watch,
> > +                             { EFL_LOOP_HANDLER_EVENT_READ,
> _ecore_signal_cb_read },
> > +                             { EFL_EVENT_DEL, _ecore_signal_cb_del });
> > +
> > +static void
> > +_ecore_signal_callback(int sig, siginfo_t *si, void *foo EINA_UNUSED)
> >  {
> > -   return sig_count;
> > +   Signal_Data sdata;
> > +
> > +   sdata.sig = sig;
> > +   sdata.info = *si;
> > +   if (sdata.sig >= 0) write(sig_pipe[1], &sdata, sizeof(sdata));
> >  }
> >
> >  static void
> > -_ecore_signal_generic_free(void *data EINA_UNUSED, void *event)
> > +_ecore_signal_callback_set(int sig, Signal_Handler func)
> >  {
> > -   free(event);
> > +   struct sigaction sa;
> > +
> > +#ifdef ECORE_SIGNAL_THREAD
> > +   if (eina_thread_self() != sig_thread)
> > +     {
> > +        fprintf(stderr, "Ecore sig handler NOT called from sigwatcher
> thread\n");
> > +     }
> > +#endif
> > +   sa.sa_sigaction = func;
> > +   sa.sa_flags = SA_RESTART | SA_SIGINFO;
> > +   sigemptyset(&sa.sa_mask);
> > +   sigaction(sig, &sa, NULL);
> >  }
> >
> > -void
> > -_ecore_signal_call(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
> > +static void
> > +_signalhandler_setup(void)
> >  {
> > -   volatile sig_atomic_t n;
> > -   sigset_t oldset, newset;
> > -   int tot;
> > +   sigset_t newset;
> > +
> > +   _ecore_signal_callback_set(SIGPIPE, _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGALRM, _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGCHLD, _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGUSR1, _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGUSR2, _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGHUP,  _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGQUIT, _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGINT,  _ecore_signal_callback);
> > +   _ecore_signal_callback_set(SIGTERM, _ecore_signal_callback);
> > +#ifdef SIGPWR
> > +   _ecore_signal_callback_set(SIGPWR,  _ecore_signal_callback);
> > +#endif
> >
> > -   if (sig_count == 0) return;
> > -   eina_evlog("+signals", NULL, 0.0, NULL);
> > +#ifndef _WIN32
> >     sigemptyset(&newset);
> >     sigaddset(&newset, SIGPIPE);
> >     sigaddset(&newset, SIGALRM);
> > @@ -180,430 +189,138 @@ _ecore_signal_call(Eo *obj, Efl_Loop_Data *pd
> EINA_UNUSED)
> >     sigaddset(&newset, SIGQUIT);
> >     sigaddset(&newset, SIGINT);
> >     sigaddset(&newset, SIGTERM);
> > -#ifdef SIGPWR
> > +# ifdef SIGPWR
> >     sigaddset(&newset, SIGPWR);
> > +# endif
> > +   pthread_sigmask(SIG_UNBLOCK, &newset, NULL);
> >  #endif
> > -   sigprocmask(SIG_BLOCK, &newset, &oldset);
> > -   if (sigchld_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGCHLD in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sigchld_count, MAXSIGQ);
> > -   tot = sigchld_count + sigusr1_count + sigusr2_count +
> > -     sighup_count + sigquit_count + sigint_count + sigterm_count
> > -#ifdef SIGPWR
> > -     + sigpwr_count
> > -#endif
> > -     ;
> > -
> > -   if (sig_count != tot)
> > -     {
> > -        ERR("sig_count (%"PRIdSIGATOMIC") != actual totals (%i) ",
> > -            sig_count, tot);
> > -        sig_count = tot;
> > -     }
> > -
> > -   for (n = 0; n < sigchld_count; n++)
> > -     {
> > -        pid_t pid;
> > -        int status;
> > -
> > -        while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
> > -          {
> > -             Ecore_Exe_Event_Del *e;
> > -
> > -             /* FIXME: If this process is set respawn, respawn with a
> suitable backoff
> > -              * period for those that need too much respawning.
> > -              */
> > -             e = _ecore_exe_event_del_new();
> > -             if (e)
> > -               {
> > -                  if (WIFEXITED(status))
> > -                    {
> > -                       e->exit_code = WEXITSTATUS(status);
> > -                       e->exited = 1;
> > -                    }
> > -                  else if (WIFSIGNALED(status))
> > -                    {
> > -                       e->exit_signal = WTERMSIG(status);
> > -                       e->signalled = 1;
> > -                    }
> > -                  e->pid = pid;
> > -                  e->exe = _ecore_exe_find(pid);
> > -
> > -                  if ((n < MAXSIGQ) && (sigchld_info[n].si_signo))
> > -                    e->data = sigchld_info[n];  /* No need to clone
> this. */
> > -
> > -                  if ((e->exe) &&
> > -                      (ecore_exe_flags_get(e->exe) &
> > -                       (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
> > -                    {
> > -     /* We want to report the Last Words of the exe, so delay this
> event.
> > -      * This is twice as relevant for stderr.
> > -      * There are three possibilities here -
> > -      *  1 There are no Last Words.
> > -      *  2 There are Last Words, they are not ready to be read.
> > -      *  3 There are Last Words, they are ready to be read.
> > -      *
> > -      * For 1 we don't want to delay, for 3 we want to delay.
> > -      * 2 is the problem.  If we check for data now and there
> > -      * is none, then there is no way to differentiate 1 and 2.
> > -      * If we don't delay, we may loose data, but if we do delay,
> > -      * there may not be data and the exit event never gets sent.
> > -      *
> > -      * Any way you look at it, there has to be some time passed
> > -      * before the exit event gets sent.  So the strategy here is
> > -      * to setup a timer event that will send the exit event after
> > -      * an arbitrary, but brief, time.
> > -      *
> > -      * This is probably paranoid, for the less paraniod, we could
> > -      * check to see for Last Words, and only delay if there are any.
> > -      * This has it's own set of problems.
> > -      */
> > -                       Efl_Loop_Timer *doomsday_clock =
> > -                         _ecore_exe_doomsday_clock_get(e->exe);
> > -                       efl_del(doomsday_clock);
> > -                       doomsday_clock =
> > -                         efl_add(EFL_LOOP_TIMER_CLASS, obj,
> > -                                 efl_loop_timer_interval_set(efl_added,
> 0.1),
> > -                                 efl_event_callback_add
> > -                                   (efl_added,
> EFL_LOOP_TIMER_EVENT_TICK,
> > -                                    _ecore_signal_exe_exit_delay, e));
> > -                       _ecore_exe_doomsday_clock_set(e->exe,
> doomsday_clock);
> > -                    }
> > -                  else
> > -                    {
> > -                       ecore_event_add(ECORE_EXE_EVENT_DEL, e,
> > -                                       _ecore_exe_event_del_free, NULL);
> > -                    }
> > -               }
> > -          }
> > -        sig_count--;
> > -     }
> > -   sigchld_count = 0;
> > -
> > -   if (sigusr1_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGUSR1 in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sigusr1_count, MAXSIGQ);
> > -   for (n = 0; n < sigusr1_count; n++)
> > -     {
> > -        Ecore_Event_Signal_User *e;
> > -
> > -        e = _ecore_event_signal_user_new();
> > -        if (e)
> > -          {
> > -             e->number = 1;
> > -
> > -             if ((n < MAXSIGQ) && (sigusr1_info[n].si_signo))
> > -               e->data = sigusr1_info[n];
> > -
> > -             ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
> > -                             _ecore_signal_generic_free, NULL);
> > -          }
> > -        sig_count--;
> > -     }
> > -   sigusr1_count = 0;
> > -
> > -   if (sigusr2_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGUSR2 in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sigusr2_count, MAXSIGQ);
> > -   for (n = 0; n < sigusr2_count; n++)
> > -     {
> > -        Ecore_Event_Signal_User *e;
> > -
> > -        e = _ecore_event_signal_user_new();
> > -        if (e)
> > -          {
> > -             e->number = 2;
> > -
> > -             if ((n < MAXSIGQ) && (sigusr2_info[n].si_signo))
> > -               e->data = sigusr2_info[n];
> > -
> > -             ecore_event_add(ECORE_EVENT_SIGNAL_USER, e,
> > -                             _ecore_signal_generic_free, NULL);
> > -          }
> > -        sig_count--;
> > -     }
> > -   sigusr2_count = 0;
> > -
> > -   if (sighup_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGHUP in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sighup_count, MAXSIGQ);
> > -   for (n = 0; n < sighup_count; n++)
> > -     {
> > -        Ecore_Event_Signal_Hup *e;
> > -
> > -        e = _ecore_event_signal_hup_new();
> > -        if (e)
> > -          {
> > -             if ((n < MAXSIGQ) && (sighup_info[n].si_signo))
> > -               e->data = sighup_info[n];
> > -
> > -             ecore_event_add(ECORE_EVENT_SIGNAL_HUP, e,
> > -                             _ecore_signal_generic_free, NULL);
> > -          }
> > -        sig_count--;
> > -     }
> > -   sighup_count = 0;
> > -
> > -   if (sigquit_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGQUIT in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sigquit_count, MAXSIGQ);
> > -   for (n = 0; n < sigquit_count; n++)
> > -     {
> > -        Ecore_Event_Signal_Exit *e;
> > -
> > -        e = _ecore_event_signal_exit_new();
> > -        if (e)
> > -          {
> > -             e->quit = 1;
> > -
> > -             if ((n < MAXSIGQ) && (sigquit_info[n].si_signo))
> > -               e->data = sigquit_info[n];
> > -
> > -             ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
> > -                             _ecore_signal_generic_free, NULL);
> > -          }
> > -        sig_count--;
> > -     }
> > -   sigquit_count = 0;
> > -
> > -   if (sigint_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGINT in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sigint_count, MAXSIGQ);
> > -   for (n = 0; n < sigint_count; n++)
> > -     {
> > -        Ecore_Event_Signal_Exit *e;
> > -
> > -        e = _ecore_event_signal_exit_new();
> > -        if (e)
> > -          {
> > -             e->interrupt = 1;
> > -
> > -             if ((n < MAXSIGQ) && (sigint_info[n].si_signo))
> > -               e->data = sigint_info[n];
> > +}
> >
> > -             ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
> > -                             _ecore_signal_generic_free, NULL);
> > -          }
> > -        sig_count--;
> > -     }
> > -   sigint_count = 0;
> > +static void *
> > +_ecore_signal_thread_watcher(void *data EINA_UNUSED, Eina_Thread t)
> > +{
> > +   eina_thread_cancellable_set(EINA_FALSE, NULL);
> > +   eina_thread_name_set(t, "Esigwatcher");
> > +   _signalhandler_setup();
> > +   for (;;) pause();
> > +   return NULL;
> > +}
> >
> > -   if (sigterm_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGTERM in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sigterm_count, MAXSIGQ);
> > -   for (n = 0; n < sigterm_count; n++)
> > +static void
> > +_ecore_signal_pipe_init(void)
> > +{
> > +   if (sig_pipe[0] == -1)
> >       {
> > -        Ecore_Event_Signal_Exit *e;
> > -
> > -        e = _ecore_event_signal_exit_new();
> > -        if (e)
> > +        if (pipe(sig_pipe) != 0)
> >            {
> > -             e->terminate = 1;
> > -
> > -             if ((n < MAXSIGQ) && (sigterm_info[n].si_signo))
> > -               e->data = sigterm_info[n];
> > -
> > -             ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
> > -                             _ecore_signal_generic_free, NULL);
> > +             sig_pipe[0] = -1;
> > +             return;
> >            }
> > -        sig_count--;
> > +        eina_file_close_on_exec(sig_pipe[0], EINA_TRUE);
> > +        eina_file_close_on_exec(sig_pipe[1], EINA_TRUE);
> > +        fcntl(sig_pipe[0], F_SETFL, O_NONBLOCK);
> >       }
> > -   sigterm_count = 0;
> > -
> > -#ifdef SIGPWR
> > -   if (sigpwr_count > MAXSIGQ)
> > -     WRN("%"PRIdSIGATOMIC" SIGPWR in queue. max queue size %i. losing "
> > -         "siginfo for extra signals.", sigpwr_count, MAXSIGQ);
> > -   for (n = 0; n < sigpwr_count; n++)
> > +#ifdef ECORE_SIGNAL_THREAD
> > +   if (!sig_thread_exists)
> >       {
> > -        Ecore_Event_Signal_Power *e;
> > -
> > -        e = _ecore_event_signal_power_new();
> > -        if (e)
> > +        if (!eina_thread_create(&sig_thread, EINA_THREAD_NORMAL,
> > +                                -1, _ecore_signal_thread_watcher, NULL))
> >            {
> > -             if ((n < MAXSIGQ) && (sigpwr_info[n].si_signo))
> > -               e->data = sigpwr_info[n];
> > -
> > -             ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e,
> > -                             _ecore_signal_generic_free, NULL);
> > +             close(sig_pipe[0]);
> > +             close(sig_pipe[1]);
> > +             sig_pipe[0] = -1;
> > +             sig_pipe[1] = -1;
> > +             return;
> >            }
> > -        sig_count--;
> > +        sig_thread_exists = EINA_TRUE;
> >       }
> > -   sigpwr_count = 0;
> > +#else
> > +   _signalhandler_setup();
> >  #endif
> > -   sig_count = 0;
> > -
> > -   sigprocmask(SIG_SETMASK, &oldset, NULL);
> > -   eina_evlog("-signals", NULL, 0.0, NULL);
> > +   if (!sig_pipe_handler)
> > +     sig_pipe_handler =
> > +       efl_add(EFL_LOOP_HANDLER_CLASS, ML_OBJ,
> > +               efl_loop_handler_fd_set(efl_added, sig_pipe[0]),
> > +               efl_loop_handler_active_set(efl_added,
> EFL_LOOP_HANDLER_FLAGS_READ),
> > +               efl_event_callback_array_add(efl_added, _event_watch(),
> NULL));
> >  }
> >
> >  static void
> > -_ecore_signal_callback_set(int            sig,
> > -                           Signal_Handler func)
> > +_ecore_signal_pipe_shutdown(void)
> >  {
> > -   struct sigaction sa;
> > -
> > -   sa.sa_sigaction = func;
> > -   sa.sa_flags = SA_RESTART | SA_SIGINFO;
> > -   sigemptyset(&sa.sa_mask);
> > -   sigaction(sig, &sa, NULL);
> > -}
> > -
> > -static void
> > -_ecore_signal_callback_ignore(int        sig EINA_UNUSED,
> > -                              siginfo_t *si EINA_UNUSED,
> > -                              void      *foo EINA_UNUSED)
> > -{
> > -}
> > -
> > -static void
> > -_ecore_signal_callback_sigchld(int        sig EINA_UNUSED,
> > -                               siginfo_t *si,
> > -                               void      *foo EINA_UNUSED)
> > -{
> > -   volatile sig_atomic_t n;
> > -   n = sigchld_count;
> > -   if (n < MAXSIGQ)
> > +   if (sig_pipe[0] != -1)
> >       {
> > -        if (si)
> > -          sigchld_info[n] = *si;
> > -        else
> > -          sigchld_info[n].si_signo = 0;
> > +        close(sig_pipe[0]);
> > +        close(sig_pipe[1]);
> > +        sig_pipe[0] = -1;
> > +        sig_pipe[1] = -1;
> >       }
> > -
> > -   sigchld_count++;
> > -   sig_count++;
> > -}
> > -
> > -static void
> > -_ecore_signal_callback_sigusr1(int        sig EINA_UNUSED,
> > -                               siginfo_t *si,
> > -                               void      *foo EINA_UNUSED)
> > -{
> > -   volatile sig_atomic_t n;
> > -   n = sigusr1_count;
> > -   if (n < MAXSIGQ)
> > +   if (sig_pipe_handler)
> >       {
> > -        if (si)
> > -          sigusr1_info[n] = *si;
> > -        else
> > -          sigusr1_info[n].si_signo = 0;
> > +        efl_del(sig_pipe_handler);
> > +        sig_pipe_handler = NULL;
> >       }
> > -   sigusr1_count++;
> > -   sig_count++;
> >  }
> >
> >  static void
> > -_ecore_signal_callback_sigusr2(int        sig EINA_UNUSED,
> > -                               siginfo_t *si,
> > -                               void      *foo EINA_UNUSED)
> > +_ecore_signal_cb_fork(void *data EINA_UNUSED)
> >  {
> > -   volatile sig_atomic_t n;
> > -   n = sigusr2_count;
> > -   if (n < MAXSIGQ)
> > -     {
> > -        if (si)
> > -          sigusr2_info[n] = *si;
> > -        else
> > -          sigusr2_info[n].si_signo = 0;
> > -     }
> > -   sigusr2_count++;
> > -   sig_count++;
> > +   _ecore_signal_pipe_shutdown();
> > +#ifdef ECORE_SIGNAL_THREAD
> > +   sig_thread_exists = EINA_FALSE;
> > +#endif
> > +   _ecore_signal_pipe_init();
> >  }
> >
> > -static void
> > -_ecore_signal_callback_sighup(int        sig EINA_UNUSED,
> > -                              siginfo_t *si,
> > -                              void      *foo EINA_UNUSED)
> > +void
> > +_ecore_signal_init(void)
> >  {
> > -   volatile sig_atomic_t n;
> > -   n = sighup_count;
> > -   if (n < MAXSIGQ)
> > -     {
> > -        if (si)
> > -          sighup_info[n] = *si;
> > -        else
> > -          sighup_info[n].si_signo = 0;
> > -     }
> > -   sighup_count++;
> > -   sig_count++;
> > -}
> > +#ifndef _WIN32
> > +   sigset_t newset;
> >
> > -static void
> > -_ecore_signal_callback_sigquit(int        sig EINA_UNUSED,
> > -                               siginfo_t *si,
> > -                               void      *foo EINA_UNUSED)
> > -{
> > -   volatile sig_atomic_t n;
> > -   n = sigquit_count;
> > -   if (n < MAXSIGQ)
> > -     {
> > -        if (si)
> > -          sigquit_info[n] = *si;
> > -        else
> > -          sigquit_info[n].si_signo = 0;
> > -     }
> > -   sigquit_count++;
> > -   sig_count++;
> > +   sigemptyset(&newset);
> > +   sigaddset(&newset, SIGPIPE);
> > +   sigaddset(&newset, SIGALRM);
> > +   sigaddset(&newset, SIGCHLD);
> > +   sigaddset(&newset, SIGUSR1);
> > +   sigaddset(&newset, SIGUSR2);
> > +   sigaddset(&newset, SIGHUP);
> > +   sigaddset(&newset, SIGQUIT);
> > +   sigaddset(&newset, SIGINT);
> > +   sigaddset(&newset, SIGTERM);
> > +# ifdef SIGPWR
> > +   sigaddset(&newset, SIGPWR);
> > +# endif
> > +   pthread_sigmask(SIG_BLOCK, &newset, NULL);
> > +#endif
> > +   _ecore_signal_pipe_init();
> > +   ecore_fork_reset_callback_add(_ecore_signal_cb_fork, NULL);
> >  }
> >
> > -static void
> > -_ecore_signal_callback_sigint(int        sig EINA_UNUSED,
> > -                              siginfo_t *si,
> > -                              void      *foo EINA_UNUSED)
> > +void
> > +_ecore_signal_shutdown(void)
> >  {
> > -   volatile sig_atomic_t n;
> > -   n = sigint_count;
> > -   if (n < MAXSIGQ)
> > -     {
> > -        if (si)
> > -          sigint_info[n] = *si;
> > -        else
> > -          sigint_info[n].si_signo = 0;
> > -     }
> > -   sigint_count++;
> > -   sig_count++;
> > +   ecore_fork_reset_callback_del(_ecore_signal_cb_fork, NULL);
> > +   _ecore_signal_pipe_shutdown();
> > +   // we probably should restore.. but not a good idea
> > +   // pthread_sigmask(SIG_SETMASK, &sig_oldset, NULL);
> >  }
> >
> > -static void
> > -_ecore_signal_callback_sigterm(int        sig EINA_UNUSED,
> > -                               siginfo_t *si,
> > -                               void      *foo EINA_UNUSED)
> > +void
> > +_ecore_signal_received_process(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd
> EINA_UNUSED)
> >  {
> > -   volatile sig_atomic_t n;
> > -   n = sigterm_count;
> > -   if (n < MAXSIGQ)
> > -     {
> > -        if (si)
> > -          sigterm_info[n] = *si;
> > -        else
> > -          sigterm_info[n].si_signo = 0;
> > -     }
> > -   sigterm_count++;
> > -   sig_count++;
> > +   // do nothing - the efl loop handler read event will handle it
> >  }
> >
> > -#ifdef SIGPWR
> > -static void
> > -_ecore_signal_callback_sigpwr(int        sig EINA_UNUSED,
> > -                              siginfo_t *si,
> > -                              void      *foo EINA_UNUSED)
> > +int
> > +_ecore_signal_count_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd
> EINA_UNUSED)
> >  {
> > -   volatile sig_atomic_t n;
> > -   n = sigpwr_count;
> > -   if (n < MAXSIGQ)
> > -     {
> > -        if (si)
> > -          sigpwr_info[n] = *si;
> > -        else
> > -          sigpwr_info[n].si_signo = 0;
> > -     }
> > -   sigpwr_count++;
> > -   sig_count++;
> > +   // we will always have 0 signals be3cause they will instead be read
> from
> > +   // a pipe fd and placed in a queue/list that
> > +   // _ecore_signal_received_process() will then walk and process/do
> > +   return 0;
> >  }
> >
> > -#endif
> > -
> >  static void
> >  _ecore_signal_exe_exit_delay(void *data, const Efl_Event *event)
> >  {
> > @@ -616,3 +333,77 @@ _ecore_signal_exe_exit_delay(void *data, const
> Efl_Event *event)
> >     efl_del(event->object);
> >  }
> >
> > +static void
> > +_ecore_signal_waitpid(Eina_Bool once, siginfo_t info)
> > +{
> > +   pid_t pid;
> > +   int status;
> > +
> > +   while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
> > +     {
> > +        Ecore_Exe_Event_Del *e = _ecore_exe_event_del_new();
> > +
> > +        //FIXME: If this process is set respawn, respawn with a
> suitable backoff
> > +        // period for those that need too much respawning.
> > +        if (e)
> > +          {
> > +             if (WIFEXITED(status))
> > +               {
> > +                  e->exit_code = WEXITSTATUS(status);
> > +                  e->exited = 1;
> > +               }
> > +             else if (WIFSIGNALED(status))
> > +               {
> > +                  e->exit_signal = WTERMSIG(status);
> > +                  e->signalled = 1;
> > +               }
> > +             e->pid = pid;
> > +             e->exe = _ecore_exe_find(pid);
> > +             e->data = info;  // No need to clone this.
> > +             if ((e->exe) &&
> > +                 (ecore_exe_flags_get(e->exe) &
> > +                  (ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR)))
> > +               {
> > +                  /* We want to report the Last Words of the exe, so
> delay this event.
> > +                   * This is twice as relevant for stderr.
> > +                   * There are three possibilities here -
> > +                   *  1 There are no Last Words.
> > +                   *  2 There are Last Words, they are not ready to be
> read.
> > +                   *  3 There are Last Words, they are ready to be read.
> > +                   *
> > +                   * For 1 we don't want to delay, for 3 we want to
> delay.
> > +                   * 2 is the problem.  If we check for data now and
> there
> > +                   * is none, then there is no way to differentiate 1
> and 2.
> > +                   * If we don't delay, we may loose data, but if we do
> delay,
> > +                   * there may not be data and the exit event never
> gets sent.
> > +                   *
> > +                   * Any way you look at it, there has to be some time
> passed
> > +                   * before the exit event gets sent.  So the strategy
> here is
> > +                   * to setup a timer event that will send the exit
> event after
> > +                   * an arbitrary, but brief, time.
> > +                   *
> > +                   * This is probably paranoid, for the less paraniod,
> we could
> > +                   * check to see for Last Words, and only delay if
> there are any.
> > +                   * This has it's own set of problems. */
> > +                  efl_del(_ecore_exe_doomsday_clock_get(e->exe));
> > +
> > +                  Efl_Loop_Timer *doomsday_clock =
> > +                    efl_add(EFL_LOOP_TIMER_CLASS, ML_OBJ,
> > +                            efl_loop_timer_interval_set(efl_added,
> 0.1),
> > +                            efl_event_callback_add
> > +                            (efl_added, EFL_LOOP_TIMER_EVENT_TICK,
> > +                             _ecore_signal_exe_exit_delay, e));
> > +                  _ecore_exe_doomsday_clock_set(e->exe,
> doomsday_clock);
> > +               }
> > +             else ecore_event_add(ECORE_EXE_EVENT_DEL, e,
> > +                                  _ecore_exe_event_del_free, NULL);
> > +          }
> > +        if (once) break;
> > +     }
> > +}
> > +
> > +static void
> > +_ecore_signal_generic_free(void *data EINA_UNUSED, void *event)
> > +{
> > +   free(event);
> > +}
> >
> > --
> >
> >
>
>
>
> --
> Gustavo Sverzut Barbieri
> --------------------------------------
> Mobile: +55 (16) 99354-9890
>
> ------------------------------------------------------------
> ------------------
> Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot
> _______________________________________________
> enlightenment-devel mailing list
> enlightenment-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
>
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to