]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
[daemon] Dump log to plymouth-crash.log on crash
authorRay Strode <rstrode@redhat.com>
Tue, 5 May 2009 14:59:57 +0000 (10:59 -0400)
committerRay Strode <rstrode@redhat.com>
Wed, 20 May 2009 21:27:51 +0000 (17:27 -0400)
This will be useful for debug purposes.

It's implemented by adding the concept of
"filters" to the logger code.  Each time a message
is logged it is passed through all registered
filter handlers and then the output of the filters
are what is actually logged.

In this case, we pass the messages through verbatim,
but also redirect them to a debug buffer.

We only do this redirection when plymouth:debug is
used.

src/libply/ply-logger.c
src/libply/ply-logger.h
src/main.c

index 7645aea56b185f07a1768ff48593f3adf2190745..df4738f354c2f961be1915810736c2d630a18ad5 100644 (file)
@@ -37,6 +37,7 @@
 #include <unistd.h>
 
 #include "ply-utils.h"
+#include "ply-list.h"
 
 #ifndef PLY_LOGGER_OPEN_FLAGS
 #define PLY_LOGGER_OPEN_FLAGS (O_WRONLY | O_TRUNC | O_CREAT | O_NOFOLLOW)
 #define PLY_LOGGER_MAX_BUFFER_CAPACITY (8 * 4096)
 #endif
 
+typedef struct
+{
+  ply_logger_filter_handler_t  handler;
+  void                        *user_data;
+} ply_logger_filter_t;
+
 struct _ply_logger
 {
   int output_fd;
@@ -60,6 +67,7 @@ struct _ply_logger
   size_t buffer_capacity;
 
   ply_logger_flush_policy_t flush_policy;
+  ply_list_t *filters;
 
   uint32_t is_enabled : 1;
   uint32_t tracing_is_enabled : 1;
@@ -233,6 +241,8 @@ ply_logger_new (void)
   logger->buffer = calloc (1, logger->buffer_capacity);
   logger->buffer_size = 0;
 
+  logger->filters = ply_list_new ();
+
   return logger;
 }
 
@@ -266,6 +276,27 @@ ply_logger_get_error_default (void)
   return logger;
 }
 
+static void
+ply_logger_free_filters (ply_logger_t *logger)
+{
+  ply_list_node_t *node;
+
+  node = ply_list_get_first_node (logger->filters);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      ply_logger_filter_t *filter;
+
+      filter = (ply_logger_filter_t *) ply_list_node_get_data (node);
+
+      next_node = ply_list_get_next_node (logger->filters, node);
+      free (filter);
+      node = next_node;
+    }
+
+  ply_list_free (logger->filters);
+}
+
 void
 ply_logger_free (ply_logger_t *logger)
 {
@@ -279,6 +310,8 @@ ply_logger_free (ply_logger_t *logger)
       close (logger->output_fd);
     }
 
+  ply_logger_free_filters (logger);
+
   free (logger->filename);
   free (logger->buffer);
   free (logger);
@@ -468,11 +501,57 @@ ply_logger_inject_bytes (ply_logger_t *logger,
                          const void   *bytes,
                          size_t        number_of_bytes)
 {
+  ply_list_node_t *node;
+  void *filtered_bytes;
+  size_t filtered_size;
+
   assert (logger != NULL);
   assert (bytes != NULL);
   assert (number_of_bytes != 0);
 
-  ply_logger_buffer (logger, bytes, number_of_bytes);
+  filtered_bytes = NULL;
+  filtered_size = 0;
+  node = ply_list_get_first_node (logger->filters);
+  while (node != NULL)
+    {
+      ply_list_node_t *next_node;
+      ply_logger_filter_t *filter;
+
+      filter = (ply_logger_filter_t *) ply_list_node_get_data (node);
+
+      next_node = ply_list_get_next_node (logger->filters, node);
+
+      if (filtered_bytes == NULL)
+        filter->handler (filter->user_data, bytes, number_of_bytes,
+                         &filtered_bytes, &filtered_size, logger);
+      else
+        {
+          void *new_bytes;
+          size_t new_size;
+
+          new_bytes = NULL;
+          new_size = 0;
+          filter->handler (filter->user_data, filtered_bytes, filtered_size,
+                           &new_bytes, &new_size, logger);
+
+          if (new_bytes != NULL)
+            {
+              free (filtered_bytes);
+              filtered_bytes = new_bytes;
+              filtered_size = new_size;
+            }
+        }
+
+      node = next_node;
+    }
+
+  if (filtered_bytes == NULL)
+    ply_logger_buffer (logger, bytes, number_of_bytes);
+  else
+    {
+      ply_logger_buffer (logger, filtered_bytes, filtered_size);
+      free (filtered_bytes);
+    }
 
   assert ((logger->flush_policy == PLY_LOGGER_FLUSH_POLICY_WHEN_ASKED)
           || (logger->flush_policy == PLY_LOGGER_FLUSH_POLICY_EVERY_TIME));
@@ -481,6 +560,21 @@ ply_logger_inject_bytes (ply_logger_t *logger,
     ply_logger_flush (logger);
 }
 
+void
+ply_logger_add_filter (ply_logger_t                *logger,
+                       ply_logger_filter_handler_t  filter_handler,
+                       void                        *user_data)
+{
+  ply_logger_filter_t *filter;
+
+  filter = calloc (1, sizeof (ply_logger_filter_t));
+
+  filter->handler = filter_handler;
+  filter->user_data = user_data;
+
+  ply_list_append_data (logger->filters, filter);
+}
+
 #ifdef PLY_ENABLE_TRACING
 void
 ply_logger_toggle_tracing (ply_logger_t *logger)
index 96b02b4044bf0a7339e4474daf52461c2ace2df1..36fe7d1accd61c19af3c75bdf0c77dd7472b9639 100644 (file)
@@ -35,6 +35,13 @@ typedef enum
   PLY_LOGGER_FLUSH_POLICY_EVERY_TIME
 } ply_logger_flush_policy_t;
 
+typedef void (* ply_logger_filter_handler_t) (void          *user_data,
+                                              const void    *in_bytes,
+                                              size_t         in_size,
+                                              void         **out_bytes,
+                                              size_t        *out_size,
+                                              ply_logger_t  *logger);
+
 #ifndef PLY_HIDE_FUNCTION_DECLARATIONS
 ply_logger_t *ply_logger_new (void);
 void ply_logger_free (ply_logger_t *logger);
@@ -54,6 +61,9 @@ bool ply_logger_is_logging (ply_logger_t *logger);
 void ply_logger_inject_bytes (ply_logger_t *logger,
                               const void   *bytes,
                               size_t number_of_bytes);
+void ply_logger_add_filter (ply_logger_t                *logger,
+                            ply_logger_filter_handler_t  filter_handler,
+                            void                        *user_data);
 #define ply_logger_inject(logger, format, args...)                             \
         ply_logger_inject_with_non_literal_format_string (logger,              \
                                                           format "", ##args)
index 8d7fdef080504988c8ef8f1148030f56de276a23..fc5e00873c62b54c55b5d7c4aa2f63b0562f1c2f 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/kd.h>
 #include <linux/vt.h>
 
+#include "ply-buffer.h"
 #include "ply-command-parser.h"
 #include "ply-boot-server.h"
 #include "ply-boot-splash.h"
@@ -114,6 +115,8 @@ static void on_escape_pressed (state_t *state);
 static void dump_details_and_quit_splash (state_t *state);
 static void update_display (state_t *state);
 
+static ply_buffer_t *debug_buffer;
+
 static void
 switch_to_vt (int vt_number)
 {
@@ -1197,10 +1200,20 @@ initialize_environment (state_t *state)
   return true;
 }
 
+static void
+on_error_message (ply_buffer_t *debug_buffer,
+                  const void   *bytes,
+                  size_t        number_of_bytes)
+{
+  ply_buffer_append_bytes (debug_buffer, bytes, number_of_bytes);
+}
+
 static void
 on_crash (int signum)
 {
     int fd;
+    const char *bytes;
+    size_t size;
 
     fd = open ("/dev/tty1", O_RDWR | O_NOCTTY);
 
@@ -1208,6 +1221,17 @@ on_crash (int signum)
 
     close (fd);
 
+    if (debug_buffer != NULL) {
+            fd = open (PLYMOUTH_LOG_DIRECTORY "/plymouth-crash.log",
+                       O_WRONLY | O_CREAT, 0600);
+            size = ply_buffer_get_size (debug_buffer);
+            bytes = ply_buffer_get_bytes (debug_buffer);
+            ply_write (fd, bytes, size);
+            close (fd);
+
+            pause ();
+    }
+
     signal (signum, SIG_DFL);
     raise(signum);
 }
@@ -1305,6 +1329,16 @@ main (int    argc,
         }
     }
 
+  if (debug)
+    {
+      debug_buffer = ply_buffer_new ();
+
+      ply_logger_add_filter (ply_logger_get_error_default (),
+                             (ply_logger_filter_handler_t)
+                             on_error_message,
+                             debug_buffer);
+    }
+
   signal (SIGABRT, on_crash);
   signal (SIGSEGV, on_crash);
 
@@ -1392,6 +1426,8 @@ main (int    argc,
   ply_trace ("freeing event loop");
   ply_event_loop_free (state.loop);
 
+  ply_buffer_free (debug_buffer);
+
   ply_trace ("exiting with code %d", exit_code);
 
   ply_free_error_log();