On Sat, 6 Jan 2018 11:23:31 -0200 Gustavo Sverzut Barbieri <[email protected]>
said:

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

i wanted something that had less ifdefs for handling windows. i already tried
sigwait and sigwaitinfo and these were seemingly not working on freebsd. i
finally went with something that worked on linux, freebsd and windows with
minimal ifdefs... :) this basically works just like signalfd but we're doing it
oursevles via regular signal handlers that have actually "always worked" and
work on windows too. well it seems to work on windows. i compiled and ran it...
ctrl+c worked... (ans since we set up a SIGINT handler and from what i read...
this is actually emulated on windows with window creating a thread to just
call this sigint handler func)...

i didn't want to use ecore_pipe as it was a legacy api ... and my tests showe
that pipe() +read() +write() worked. maybe they didn't in the past on windows
and thats why ecore_pipe uses recv+send+closesocket?

> On Sat, Jan 6, 2018 at 7:51 AM, Carsten Haitzler <[email protected]> wrote:
> > raster pushed a commit to branch master.
> >
> > http://git.enlightenment.org/core/efl.git/commit/?id=ba16dee6b3d5f84e0184c86b64d5fe54e32b4966
> >
> > commit ba16dee6b3d5f84e0184c86b64d5fe54e32b4966
> > Author: Carsten Haitzler (Rasterman) <[email protected]>
> > 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
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
> 


-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
Carsten Haitzler - [email protected]


------------------------------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to