From 2ade4204790bacb04c04a23b258a58e64bbbab10 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 3 Dec 2011 17:38:07 -0600 Subject: [PATCH] netlink: consolidate netlink monitor error handling and initialization The fact that any of this code was in main.c was a hangover from a long time ago and it should really go with the rest of the netlink monitor code. --- src/main.c | 83 +------------------------- src/nm-device-wired.c | 9 +-- src/nm-netlink-monitor.c | 122 ++++++++++++++++++++++++++------------- src/nm-netlink-monitor.h | 5 +- 4 files changed, 88 insertions(+), 131 deletions(-) diff --git a/src/main.c b/src/main.c index 8f275b1641..95d3af03d8 100644 --- a/src/main.c +++ b/src/main.c @@ -67,80 +67,6 @@ static NMManager *manager = NULL; static GMainLoop *main_loop = NULL; static int quit_pipe[2] = { -1, -1 }; -typedef struct { - time_t time; - GQuark domain; - guint32 code; - guint32 count; -} MonitorInfo; - -static gboolean -detach_monitor (gpointer data) -{ - nm_log_warn (LOGD_HW, "detaching netlink event monitor"); - nm_netlink_monitor_detach (NM_NETLINK_MONITOR (data)); - return FALSE; -} - -static void -nm_error_monitoring_device_link_state (NMNetlinkMonitor *monitor, - GError *error, - gpointer user_data) -{ - MonitorInfo *info = (MonitorInfo *) user_data; - time_t now; - - now = time (NULL); - - if ( (info->domain != error->domain) - || (info->code != error->code) - || (info->time && now > info->time + 10)) { - /* FIXME: Try to handle the error instead of just printing it. */ - nm_log_warn (LOGD_HW, "error monitoring device for netlink events: %s\n", error->message); - - info->time = now; - info->domain = error->domain; - info->code = error->code; - info->count = 0; - } - - info->count++; - if (info->count > 100) { - /* Broken drivers will sometimes cause a flood of netlink errors. - * rh #459205, novell #443429, lp #284507 - */ - nm_log_warn (LOGD_HW, "excessive netlink errors ocurred, disabling netlink monitor."); - nm_log_warn (LOGD_HW, "link change events will not be processed."); - g_idle_add_full (G_PRIORITY_HIGH, detach_monitor, monitor, NULL); - } -} - -static gboolean -nm_monitor_setup (GError **error) -{ - NMNetlinkMonitor *monitor; - MonitorInfo *info; - - monitor = nm_netlink_monitor_get (); - if (!nm_netlink_monitor_open_connection (monitor, error)) { - g_object_unref (monitor); - return FALSE; - } - - info = g_new0 (MonitorInfo, 1); - g_signal_connect_data (G_OBJECT (monitor), "error", - G_CALLBACK (nm_error_monitoring_device_link_state), - info, - (GClosureNotify) g_free, - 0); - nm_netlink_monitor_attach (monitor); - - /* Request initial status of cards */ - nm_netlink_monitor_request_status (monitor, NULL); - - return TRUE; -} - static gboolean quit_early = FALSE; static void @@ -431,6 +357,7 @@ main (int argc, char *argv[]) NMFirewallManager *fw_mgr = NULL; NMSettings *settings = NULL; NMConfig *config; + NMNetlinkMonitor *monitor = NULL; GError *error = NULL; gboolean wrote_pidfile = FALSE; @@ -600,12 +527,8 @@ main (int argc, char *argv[]) main_loop = g_main_loop_new (NULL, FALSE); - /* Create watch functions that monitor cards for link status. */ - if (!nm_monitor_setup (&error)) { - nm_log_err (LOGD_CORE, "failed to start monitoring devices: %s.", - error && error->message ? error->message : "(unknown)"); - goto done; - } + /* Create netlink monitor object */ + monitor = nm_netlink_monitor_get (); /* Initialize our DBus service & connection */ dbus_mgr = nm_dbus_manager_get (); diff --git a/src/nm-device-wired.c b/src/nm-device-wired.c index 03ca0d2e10..967216d136 100644 --- a/src/nm-device-wired.c +++ b/src/nm-device-wired.c @@ -243,14 +243,7 @@ constructor (GType type, /* Request link state again just in case an error occurred getting the * initial link state. */ - if (!nm_netlink_monitor_request_status (priv->monitor, &error)) { - nm_log_warn (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), - "(%s): couldn't request carrier state: (%d) %s", - nm_device_get_iface (NM_DEVICE (self)), - error ? error->code : -1, - (error && error->message) ? error->message : "unknown"); - g_clear_error (&error); - } + nm_netlink_monitor_request_status (priv->monitor); } else { nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), "(%s): driver '%s' does not support carrier detection.", diff --git a/src/nm-netlink-monitor.c b/src/nm-netlink-monitor.c index 9b8dac5cb3..29a21e3c70 100644 --- a/src/nm-netlink-monitor.c +++ b/src/nm-netlink-monitor.c @@ -76,7 +76,6 @@ enum { NOTIFICATION = 0, CARRIER_ON, CARRIER_OFF, - ERROR, LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -84,11 +83,60 @@ static guint signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE (NMNetlinkMonitor, nm_netlink_monitor, G_TYPE_OBJECT); +/****************************************************************/ + +static gboolean +detach_monitor (gpointer data) +{ + nm_log_warn (LOGD_HW, "detaching netlink event monitor"); + nm_netlink_monitor_detach (NM_NETLINK_MONITOR (data)); + return FALSE; +} + +static void +log_error_limited (NMNetlinkMonitor *monitor, guint32 code, const char *fmt, ...) +{ + static time_t rl_time = 0; + static guint32 rl_code = 0; + static guint32 rl_count = 0; + va_list args; + char *msg; + time_t now; + + g_return_if_fail (monitor != NULL); + + now = time (NULL); + + if ((code != rl_code) || (now > rl_time + 10)) { + va_start (args, fmt); + msg = g_strdup_vprintf (fmt, args); + va_end (args); + + nm_log_warn (LOGD_HW, "error monitoring device for netlink events: %s\n", msg); + g_free (msg); + + rl_time = now; + rl_code = code; + rl_count = 0; + } + + rl_count++; + if (rl_count > 100) { + /* Broken drivers will sometimes cause a flood of netlink errors. + * rh #459205, novell #443429, lp #284507 + */ + nm_log_warn (LOGD_HW, "excessive netlink errors ocurred, disabling netlink monitor."); + nm_log_warn (LOGD_HW, "link change events will not be processed."); + g_idle_add_full (G_PRIORITY_HIGH, detach_monitor, monitor, NULL); + } +} + +/****************************************************************/ + static void link_msg_handler (struct nl_object *obj, void *arg) { NMNetlinkMonitor *self = NM_NETLINK_MONITOR (arg); - GError *error; struct rtnl_link *filter; struct rtnl_link *link_obj; guint flags; @@ -96,12 +144,9 @@ link_msg_handler (struct nl_object *obj, void *arg) filter = rtnl_link_alloc (); if (!filter) { - error = g_error_new (NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, - _("error processing netlink message: %s"), - nl_geterror (ENOMEM)); - g_signal_emit (self, signals[ERROR], 0, error); - g_error_free (error); + log_error_limited (self, NM_NETLINK_MONITOR_ERROR_BAD_ALLOC, + _("error processing netlink message: %s"), + nl_geterror (ENOMEM)); return; } @@ -195,7 +240,6 @@ event_handler (GIOChannel *channel, { NMNetlinkMonitor *self = (NMNetlinkMonitor *) user_data; NMNetlinkMonitorPrivate *priv; - GError *error = NULL; int err; g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), TRUE); @@ -204,22 +248,17 @@ event_handler (GIOChannel *channel, g_return_val_if_fail (priv->event_id > 0, TRUE); if (io_condition & ERROR_CONDITIONS) { - const char *err_msg; + const char *err_msg = _("error occurred while waiting for data on socket"); int err_code = 0; socklen_t err_len = sizeof (err_code); /* Grab error information */ if (getsockopt (g_io_channel_unix_get_fd (channel), - SOL_SOCKET, SO_ERROR, (void *) &err_code, &err_len)) + SOL_SOCKET, SO_ERROR, + (void *) &err_code, &err_len) == 0) err_msg = strerror (err_code); - else - err_msg = _("error occurred while waiting for data on socket"); - error = g_error_new (NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, - "%s", err_msg); - g_signal_emit (self, signals[ERROR], 0, error); - g_error_free (error); + log_error_limited (self, NM_NETLINK_MONITOR_ERROR_WAITING_FOR_SOCKET_DATA, "%s", err_msg); return TRUE; } else if (io_condition & DISCONNECT_CONDITIONS) return FALSE; @@ -229,12 +268,9 @@ event_handler (GIOChannel *channel, /* Process the netlink messages */ err = nl_recvmsgs_default (priv->nlh_event); if (err < 0) { - error = g_error_new (NM_NETLINK_MONITOR_ERROR, - NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, - _("error processing netlink message: %s"), - nl_geterror (err)); - g_signal_emit (self, signals[ERROR], 0, error); - g_error_free (error); + log_error_limited (self, NM_NETLINK_MONITOR_ERROR_PROCESSING_MESSAGE, + _("error processing netlink message: %s"), + nl_geterror (err)); } return TRUE; @@ -578,20 +614,18 @@ deferred_emit_carrier_state (gpointer user_data) return FALSE; } -gboolean -nm_netlink_monitor_request_status (NMNetlinkMonitor *self, GError **error) +void +nm_netlink_monitor_request_status (NMNetlinkMonitor *self) { NMNetlinkMonitorPrivate *priv; - g_return_val_if_fail (NM_IS_NETLINK_MONITOR (self), FALSE); + g_return_if_fail (NM_IS_NETLINK_MONITOR (self)); priv = NM_NETLINK_MONITOR_GET_PRIVATE (self); /* Schedule the carrier state emission */ if (!priv->request_status_id) priv->request_status_id = g_idle_add (deferred_emit_carrier_state, self); - - return TRUE; } typedef struct { @@ -778,10 +812,26 @@ NMNetlinkMonitor * nm_netlink_monitor_get (void) { static NMNetlinkMonitor *singleton = NULL; + GError *error = NULL; - if (!singleton) - singleton = NM_NETLINK_MONITOR (g_object_new (NM_TYPE_NETLINK_MONITOR, NULL)); - else + if (!singleton) { + singleton = (NMNetlinkMonitor *) g_object_new (NM_TYPE_NETLINK_MONITOR, NULL); + g_return_val_if_fail (singleton != NULL, NULL); + + if (nm_netlink_monitor_open_connection (singleton, &error)) { + nm_netlink_monitor_attach (singleton); + /* Request initial status of cards */ + nm_netlink_monitor_request_status (singleton); + } else { + nm_log_warn (LOGD_HW, "Failed to connect to netlink: (%d) %s", + error ? error->code : 0, + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + + g_object_unref (singleton); + singleton = NULL; + } + } else g_object_ref (singleton); return singleton; @@ -860,14 +910,6 @@ nm_netlink_monitor_class_init (NMNetlinkMonitorClass *monitor_class) G_STRUCT_OFFSET (NMNetlinkMonitorClass, carrier_off), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); - - signals[ERROR] = - g_signal_new ("error", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMNetlinkMonitorClass, error), - NULL, NULL, g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); } GQuark diff --git a/src/nm-netlink-monitor.h b/src/nm-netlink-monitor.h index 5c1fa33990..4e0787bdc5 100644 --- a/src/nm-netlink-monitor.h +++ b/src/nm-netlink-monitor.h @@ -58,7 +58,6 @@ typedef struct { void (*notification) (NMNetlinkMonitor *monitor, struct nl_msg *msg); void (*carrier_on) (NMNetlinkMonitor *monitor, int index); void (*carrier_off) (NMNetlinkMonitor *monitor, int index); - void (*error) (NMNetlinkMonitor *monitor, GError *error); } NMNetlinkMonitorClass; @@ -83,8 +82,8 @@ void nm_netlink_monitor_unsubscribe (NMNetlinkMonitor *monitor gboolean nm_netlink_monitor_request_ip6_info (NMNetlinkMonitor *monitor, GError **error); -gboolean nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor, - GError **error); +void nm_netlink_monitor_request_status (NMNetlinkMonitor *monitor); + gboolean nm_netlink_monitor_get_flags_sync (NMNetlinkMonitor *monitor, guint32 ifindex, guint32 *ifflags,