raster pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=347c29b952f5bf54741f67e884b0b3dc3cb37b16

commit 347c29b952f5bf54741f67e884b0b3dc3cb37b16
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
Date:   Sat Jan 2 15:22:13 2021 +0000

    watchdog - add a watchdog thread that pings mainloop every 10sec
    
    if the main loop were to hang for some reason, this would detect it,
    forcibly exit e and e_start can restart e again so things are working.
    
    @feat
---
 TODO                   |  2 --
 src/bin/e_includes.h   |  1 +
 src/bin/e_main.c       |  2 ++
 src/bin/e_start_main.c |  6 ++++
 src/bin/e_watchdog.c   | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/bin/e_watchdog.h   | 10 ++++++
 src/bin/meson.build    |  2 ++
 7 files changed, 107 insertions(+), 2 deletions(-)

diff --git a/TODO b/TODO
index b157c4867..dbe7ece39 100644
--- a/TODO
+++ b/TODO
@@ -181,8 +181,6 @@ TODO:
    logging like tables, icons, timelines and graphs that can be output
    in text emulation and to screen - change eina log to go into here
    with eina_log_print_cb_set() )
-* watchdog: add watchdog handling to e_start to detect a hung e
-  * also detect if frames stop rendering but loop ok?
 * settings: config dialog redo and simplification
   * simplify the config and remove useless options
     * focus on new simpler config dialog(s) first
diff --git a/src/bin/e_includes.h b/src/bin/e_includes.h
index b3611268d..894e4f1b2 100644
--- a/src/bin/e_includes.h
+++ b/src/bin/e_includes.h
@@ -153,6 +153,7 @@
 #include "e_hints.h"
 #include "e_comp_x_devices.h"
 #include "e_comp_x_randr.h"
+#include "e_watchdog.h"
 
 #ifdef HAVE_WAYLAND
 # include "e_comp_wl.h"
diff --git a/src/bin/e_main.c b/src/bin/e_main.c
index 6a9eab315..165cb7258 100644
--- a/src/bin/e_main.c
+++ b/src/bin/e_main.c
@@ -1086,6 +1086,7 @@ main(int argc, char **argv)
         E_LIST_FOREACH(e_comp->zones, e_comp_canvas_zone_restarted);
      }
 
+   e_watchdog_begin();
    TS("MAIN LOOP AT LAST");
    if (!setjmp(x_fatal_buff))
      {
@@ -1094,6 +1095,7 @@ main(int argc, char **argv)
      }
    else
      CRI("FATAL: X Died. Connection gone. Abbreviated Shutdown\n");
+   e_watchdog_end();
    e_main_loop_running = EINA_FALSE;
 
    inloop = EINA_FALSE;
diff --git a/src/bin/e_start_main.c b/src/bin/e_start_main.c
index ebe893710..0b4812794 100644
--- a/src/bin/e_start_main.c
+++ b/src/bin/e_start_main.c
@@ -861,6 +861,12 @@ not_done:
                   restart = EINA_TRUE;
                   done = EINA_TRUE;
                }
+             else if (WEXITSTATUS(status) == 121)
+               {
+                  putenv("E_RESTART_OK=1");
+                  restart = EINA_TRUE;
+                  done = EINA_TRUE;
+               }
              else if (WEXITSTATUS(status) == 111)
                {
                   putenv("E_RESTART_OK=1");
diff --git a/src/bin/e_watchdog.c b/src/bin/e_watchdog.c
new file mode 100644
index 000000000..e98050ff1
--- /dev/null
+++ b/src/bin/e_watchdog.c
@@ -0,0 +1,86 @@
+#include "e.h"
+
+static Ecore_Thread *_watchdog_thread = NULL;
+static Ecore_Pipe *_watchdog_pipe = NULL;
+static unsigned long last_seq = 0;
+
+static void
+_cb_watchdog_thread_pingpong_pipe(void *data EINA_UNUSED, void *buf, unsigned 
int bytes)
+{
+   unsigned long long *seq = buf;
+   unsigned long long seq_num = bytes / sizeof(int);
+
+   if (seq_num < 1) return; // XXX: error
+   last_seq = seq[seq_num - 1];
+}
+
+static void
+_cb_watchdog_thread_pingpong(void *data EINA_UNUSED, Ecore_Thread *thread)
+{
+   unsigned long long *seq_new;
+   unsigned long long seq = 0;
+
+   while (!ecore_thread_check(thread))
+     {
+        // send ping
+        seq_new = malloc(sizeof(unsigned long));
+        if (seq_new)
+          {
+             seq++;
+             *seq_new = seq;
+             ecore_thread_feedback(thread, seq_new);
+             // wait for ping from mainloop upto 10 sec
+             if (ecore_pipe_wait(_watchdog_pipe, 1, 10.0) < 1)
+               {
+                  printf("WD: Enlightenment main loop hung. No response to 
ping for 10sec\n");
+                  // do hard-exit as cleanup isnt doable
+                  _exit(121);
+               }
+             // wait another 10 sec before pinging
+             sleep(10);
+          }
+        else
+          {
+             printf("WD: Watchdog response alloc fail!!!!\n");
+             // XXX: alloc fail
+             break;
+          }
+     }
+}
+
+static void
+_cb_watchdog_thread_pingpong_reply(void *data EINA_UNUSED, Ecore_Thread 
*thread EINA_UNUSED, void *msg)
+{
+   // repluy back to mainloop with same ping number
+   unsigned long long *seq = msg;
+   ecore_pipe_write(_watchdog_pipe, seq, sizeof(unsigned long long));
+   free(seq);
+}
+
+static void
+_cb_watchdog_thread_pingpong_end(void *data EINA_UNUSED, Ecore_Thread *thread 
EINA_UNUSED)
+{
+   ecore_pipe_del(_watchdog_pipe);
+   _watchdog_pipe = NULL;
+   _watchdog_thread = NULL;
+}
+
+E_API void
+e_watchdog_begin(void)
+{
+   // set up main-loop ping-pong to a thread
+   _watchdog_pipe = ecore_pipe_add(_cb_watchdog_thread_pingpong_pipe, NULL);
+   _watchdog_thread = ecore_thread_feedback_run
+     (_cb_watchdog_thread_pingpong,
+      _cb_watchdog_thread_pingpong_reply,
+      _cb_watchdog_thread_pingpong_end,
+      NULL,
+      NULL, EINA_TRUE);
+}
+
+E_API void
+e_watchdog_end(void)
+{
+   if (_watchdog_thread) ecore_thread_cancel(_watchdog_thread);
+   _watchdog_thread = NULL;
+}
diff --git a/src/bin/e_watchdog.h b/src/bin/e_watchdog.h
new file mode 100644
index 000000000..dc471faf0
--- /dev/null
+++ b/src/bin/e_watchdog.h
@@ -0,0 +1,10 @@
+#ifdef E_TYPEDEFS
+#else
+# ifndef E_WATCHDOG_H
+#  define E_WATCHDOG_H
+
+E_API void e_watchdog_begin(void);
+E_API void e_watchdog_end(void);
+
+# endif
+#endif
diff --git a/src/bin/meson.build b/src/bin/meson.build
index c796652b2..36abfa2ad 100644
--- a/src/bin/meson.build
+++ b/src/bin/meson.build
@@ -186,6 +186,7 @@ src = [
   'e_user.c',
   'e_utils.c',
   'e_video.c',
+  'e_watchdog.c',
   'e_widget_aspect.c',
   'e_widget_button.c',
   'e_widget.c',
@@ -363,6 +364,7 @@ hdr = [
   'e_user.h',
   'e_utils.h',
   'e_video.h',
+  'e_watchdog.h',
   'e_widget_aspect.h',
   'e_widget_button.h',
   'e_widget_check.h',

-- 


Reply via email to