From: Ray Strode Date: Tue, 5 May 2009 14:59:57 +0000 (-0400) Subject: [daemon] Dump log to plymouth-crash.log on crash X-Git-Tag: 0.7.0~186 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=77dbc07593109a9010866cf62efa5c92cf9aa8b4;p=thirdparty%2Fplymouth.git [daemon] Dump log to plymouth-crash.log on crash 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. --- diff --git a/src/libply/ply-logger.c b/src/libply/ply-logger.c index 7645aea5..df4738f3 100644 --- a/src/libply/ply-logger.c +++ b/src/libply/ply-logger.c @@ -37,6 +37,7 @@ #include #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) @@ -50,6 +51,12 @@ #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) diff --git a/src/libply/ply-logger.h b/src/libply/ply-logger.h index 96b02b40..36fe7d1a 100644 --- a/src/libply/ply-logger.h +++ b/src/libply/ply-logger.h @@ -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) diff --git a/src/main.c b/src/main.c index 8d7fdef0..fc5e0087 100644 --- a/src/main.c +++ b/src/main.c @@ -37,6 +37,7 @@ #include #include +#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();