cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=da5fcb8ea07f69f1348f0c2c86cc408cf5184e30

commit da5fcb8ea07f69f1348f0c2c86cc408cf5184e30
Author: Mike Blumenkrantz <zm...@samsung.com>
Date:   Thu Sep 19 14:52:23 2019 -0400

    ecore/signal: increase maximum signal throughput
    
    this adds 4 more signal handling fds and loops over them for reading/writing
    signal info in order to handle more signals when the buffer of one (or more)
    pipes is full
    
    also update the unit test to verify that we are receiving all the events 
without
    dropping any and bump the number of signals to 2000 since we should now be 
able to
    handle that many
    
    Reviewed-by: Cedric BAIL <cedric.b...@free.fr>
    Differential Revision: https://phab.enlightenment.org/D10027
---
 src/lib/ecore/ecore_signal.c     | 274 ++++++++++++++++++++-------------------
 src/tests/ecore/ecore_test_job.c |  18 ++-
 2 files changed, 158 insertions(+), 134 deletions(-)

diff --git a/src/lib/ecore/ecore_signal.c b/src/lib/ecore/ecore_signal.c
index c3e5b0fda9..eebb692276 100644
--- a/src/lib/ecore/ecore_signal.c
+++ b/src/lib/ecore/ecore_signal.c
@@ -34,8 +34,10 @@ static void _ecore_signal_generic_free(void *data, void 
*event);
 
 typedef void (*Signal_Handler)(int sig, siginfo_t *si, void *foo);
 
-static int sig_pipe[2] = { -1, -1 }; // [0] == read, [1] == write
-static Eo *sig_pipe_handler = NULL;
+#define NUM_PIPES 5
+
+static int sig_pipe[NUM_PIPES][2] = {{ -1 }}; // [0] == read, [1] == write
+static Eo *sig_pipe_handler[NUM_PIPES] = {NULL};
 static Eina_Spinlock sig_pid_lock;
 static Eina_List *sig_pid_info_list = NULL;
 
@@ -48,114 +50,111 @@ typedef struct _Signal_Data
    siginfo_t info;
 } Signal_Data;
 
-static Eina_Bool
+static void
 _ecore_signal_pipe_read(Eo *obj)
 {
    Signal_Data sdata;
    int ret;
 
-   if (pipe_dead) return EINA_TRUE;
-   ret = read(sig_pipe[0], &sdata, sizeof(sdata));
-   if (ret != sizeof(sdata)) return EINA_FALSE;
-   switch (sdata.sig)
+   if (pipe_dead) return;
+   for (unsigned int i = 0; i < NUM_PIPES; i++)
      {
-      case SIGPIPE:
-        break;
-      case SIGALRM:
-        break;
-      case SIGCHLD:
-        _ecore_signal_waitpid(EINA_FALSE, sdata.info);
-        break;
-      case SIGUSR1:
-      case SIGUSR2:
+        while (1)
           {
-             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);
-               }
-             Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
-             if (loop)
-               {
-                  if (sdata.sig == SIGUSR1)
-                    efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_USR1, 
NULL);
-                  else
-                    efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_USR2, 
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);
-               }
-             Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
-             if (loop)
-               efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_HUP, 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);
-               }
-             Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
-             if (loop)
-               efl_event_callback_call(loop, EFL_LOOP_EVENT_QUIT, NULL);
-          }
-        break;
-#ifdef SIGPWR
-      case SIGPWR:
-          {
-             Ecore_Event_Signal_Power *e = _ecore_event_signal_power_new();
-             if (e)
+             ret = read(sig_pipe[i][0], &sdata, sizeof(sdata));
+
+             /* read as many signals as we can, trying again if we get 
interrupted */
+             if ((ret != sizeof(sdata)) && (errno != EINTR)) break;
+             switch (sdata.sig)
                {
-                  e->data = sdata.info;
-                  ecore_event_add(ECORE_EVENT_SIGNAL_POWER, e,
-                                  _ecore_signal_generic_free, NULL);
+                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);
+                         }
+                       Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
+                       if (loop)
+                         {
+                            if (sdata.sig == SIGUSR1)
+                              efl_event_callback_call(loop, 
EFL_APP_EVENT_SIGNAL_USR1, NULL);
+                            else
+                              efl_event_callback_call(loop, 
EFL_APP_EVENT_SIGNAL_USR2, 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);
+                         }
+                       Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
+                       if (loop)
+                         efl_event_callback_call(loop, 
EFL_APP_EVENT_SIGNAL_HUP, 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);
+                         }
+                       Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
+                       if (loop)
+                         efl_event_callback_call(loop, EFL_LOOP_EVENT_QUIT, 
NULL);
+                    }
+                  break;
+          #ifdef SIGPWR
+                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
+                default:
+                  break;
                }
-          }
-        break;
-#endif
-      default:
-        break;
+        }
      }
-   return EINA_TRUE;
 }
 
 static void
 _ecore_signal_cb_read(void *data EINA_UNUSED, const Efl_Event *event 
EINA_UNUSED)
 {
-   while (_ecore_signal_pipe_read(event->object));
-}
-
-static void
-_ecore_signal_cb_del(void *data EINA_UNUSED, const Efl_Event *event)
-{
-   if (event->object == sig_pipe_handler) sig_pipe_handler = NULL;
+   _ecore_signal_pipe_read(event->object);
 }
 
-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)
 {
@@ -168,17 +167,25 @@ _ecore_signal_callback(int sig, siginfo_t *si, void *foo 
EINA_UNUSED)
      {
         int err = errno;
         if (pipe_dead) return;
-        do
+        for (unsigned int i = 0; i < NUM_PIPES; i++)
           {
-             const ssize_t bytes = write(sig_pipe[1], &sdata, sizeof(sdata));
-             if (EINA_UNLIKELY(bytes != sizeof(sdata)))
+             do
                {
-                  err = errno;
-                  ERR("write() failed: %d: %s", err, strerror(err));
-               }
-             errno = err;
-             /* loop if we got preempted */
-          } while (err == EINTR);
+                  err = 0;
+                  const ssize_t bytes = write(sig_pipe[i][1], &sdata, 
sizeof(sdata));
+                  if (EINA_UNLIKELY(bytes != sizeof(sdata)))
+                    {
+                       err = errno;
+                       if (err == EINTR)
+                         DBG("signal pipe %u full", i);
+                       else if (i == NUM_PIPES - 1) //only print errors on 
last pipe
+                         ERR("write() failed: %d: %s", err, strerror(err));
+                    }
+                  errno = err;
+                  /* loop if we got preempted */
+               } while (err == EINTR);
+             if (!err) break;
+          }
      }
    switch (sig)
      {
@@ -242,45 +249,52 @@ static void
 _ecore_signal_pipe_init(void)
 {
    eina_spinlock_new(&sig_pid_lock);
-   if (sig_pipe[0] == -1)
+   _signalhandler_setup();
+   if (sig_pipe[0][0] == -1)
      {
-        if (pipe(sig_pipe) != 0)
+        for (unsigned int i = 0; i < NUM_PIPES; i++)
           {
-             sig_pipe[0] = -1;
-             return;
-          }
-        eina_file_close_on_exec(sig_pipe[0], EINA_TRUE);
-        eina_file_close_on_exec(sig_pipe[1], EINA_TRUE);
-        if (fcntl(sig_pipe[0], F_SETFL, O_NONBLOCK) < 0)
-          ERR("can't set pipe to NONBLOCK");
-        if (fcntl(sig_pipe[1], F_SETFL, O_NONBLOCK) < 0)
-          ERR("can't set pipe to NONBLOCK");
+            if (pipe(sig_pipe[i]) != 0)
+              {
+                 CRI("failed setting up signal pipes! %s", strerror(errno));
+                 for (unsigned int j = 0; j < i; j++)
+                   {
+                      close(sig_pipe[j][0]);
+                      close(sig_pipe[j][1]);
+                   }
+                 memset(sig_pipe, -1, sizeof(sig_pipe));
+                 return;
+              }
+            eina_file_close_on_exec(sig_pipe[i][0], EINA_TRUE);
+            eina_file_close_on_exec(sig_pipe[i][1], EINA_TRUE);
+            if (fcntl(sig_pipe[i][0], F_SETFL, O_NONBLOCK) < 0)
+              ERR("can't set pipe to NONBLOCK");
+            if (fcntl(sig_pipe[i][1], F_SETFL, O_NONBLOCK) < 0)
+              ERR("can't set pipe to NONBLOCK");
+            efl_add(EFL_LOOP_HANDLER_CLASS, ML_OBJ,
+                    efl_loop_handler_fd_set(efl_added, sig_pipe[i][0]),
+                    efl_loop_handler_active_set(efl_added, 
EFL_LOOP_HANDLER_FLAGS_READ),
+                    efl_event_callback_add(efl_added, 
EFL_LOOP_HANDLER_EVENT_READ, _ecore_signal_cb_read, NULL),
+                    efl_wref_add(efl_added, &sig_pipe_handler[i])
+                    );
 
+          }
      }
-   _signalhandler_setup();
-   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_pipe_shutdown(void)
 {
-   if (sig_pipe_handler)
+   if (sig_pipe[0][0] != -1)
      {
-        efl_del(sig_pipe_handler);
-        sig_pipe_handler = NULL;
-     }
-   if (sig_pipe[0] != -1)
-     {
-        close(sig_pipe[0]);
-        close(sig_pipe[1]);
-        sig_pipe[0] = -1;
-        sig_pipe[1] = -1;
+        for (unsigned int i = 0; i < NUM_PIPES; i++)
+          {
+             close(sig_pipe[i][0]);
+             close(sig_pipe[i][1]);
+             efl_del(sig_pipe_handler[i]);
+          }
      }
+   memset(sig_pipe, -1, sizeof(sig_pipe));
    eina_spinlock_free(&sig_pid_lock);
 }
 
diff --git a/src/tests/ecore/ecore_test_job.c b/src/tests/ecore/ecore_test_job.c
index 7f3e6ad7b4..688e8abe7e 100644
--- a/src/tests/ecore/ecore_test_job.c
+++ b/src/tests/ecore/ecore_test_job.c
@@ -29,21 +29,31 @@ EFL_START_TEST(ecore_test_job)
 EFL_END_TEST
 
 #ifndef _WIN32
+#define NUM_SIGNALS 2000
+static Eina_Bool
+_signal_cb(void *data, int t EINA_UNUSED, void *ev EINA_UNUSED)
+{
+   int *called = data;
+   (*called)++;
+   if (*called == NUM_SIGNALS) ecore_main_loop_quit();
+   return ECORE_CALLBACK_RENEW;
+}
+
 static void
 _ecore_signal_job(void *data EINA_UNUSED)
 {
-   EXPECT_ERROR_START;
-   for (unsigned int i = 0; i < 1000; i++)
+   for (unsigned int i = 0; i < NUM_SIGNALS; i++)
      raise(SIGUSR2);
-   ecore_main_loop_quit();
-   EXPECT_ERROR_END;
 }
 
 EFL_START_TEST(ecore_test_job_signal)
 {
+   int called = 0;
    ecore_job_add(_ecore_signal_job, NULL);
+   ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER, _signal_cb, &called);
 
    ecore_main_loop_begin();
+   ck_assert_int_eq(called, NUM_SIGNALS);
 }
 EFL_END_TEST
 #endif

-- 


Reply via email to