From 058a678f894ccfd9415f29afdcc30e7906ae0740 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 23 Aug 2004 16:45:30 +0000 Subject: [PATCH] 2004-08-23 Dan Williams * initscript/NetworkManager - Use NMLaunchHelper rather than sleeping * initscript/NMLaunchHelper.c Makefile.am - Add helper program that exits only when NM activates a device, or 10 seconds have passed, whichever happens first. This stops the boot processes until we have a network connection, which NM can't do because it daemonizes and brings the connection up in the background. Allows stuff like NFS to not die. git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@59 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 13 +++ initscript/Makefile.am | 14 +++ initscript/NMLaunchHelper.c | 169 ++++++++++++++++++++++++++++++++++++ initscript/NetworkManager | 2 +- 4 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 initscript/NMLaunchHelper.c diff --git a/ChangeLog b/ChangeLog index e48700eee7..74ef700027 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2004-08-23 Dan Williams + + * initscript/NetworkManager + - Use NMLaunchHelper rather than sleeping + + * initscript/NMLaunchHelper.c + Makefile.am + - Add helper program that exits only when NM activates a device, + or 10 seconds have passed, whichever happens first. This + stops the boot processes until we have a network connection, + which NM can't do because it daemonizes and brings the connection + up in the background. Allows stuff like NFS to not die. + 2004-08-20 Dan Williams * info-daemon/NetworkManagerInfoPassphraseDialog.c diff --git a/initscript/Makefile.am b/initscript/Makefile.am index 28cb50c619..7529d0cb31 100644 --- a/initscript/Makefile.am +++ b/initscript/Makefile.am @@ -1,3 +1,17 @@ +INCLUDES = \ + $(NM_CFLAGS) \ + -Wall \ + -DDBUS_API_SUBJECT_TO_CHANGE \ + -DG_DISABLE_DEPRECATED \ + -DBINDIR=\"$(bindir)\" \ + -DDATADIR=\"$(datadir)\" + +bin_PROGRAMS = NMLaunchHelper + +NMLaunchHelper_SOURCES = NMLaunchHelper.c + +NMLaunchHelper_LDADD = $(NM_LIBS) + EXTRA_DIST = NetworkManager initddir = $(sysconfdir)/rc.d/init.d diff --git a/initscript/NMLaunchHelper.c b/initscript/NMLaunchHelper.c new file mode 100644 index 0000000000..9a3aaa298d --- /dev/null +++ b/initscript/NMLaunchHelper.c @@ -0,0 +1,169 @@ +/* NMLaunchHelper - Blocks until NetworkManager has a connection, or until + * a timeout occurs. This is needed because NM daemonizes + * but startup scripts continue blindly as if the network + * were up. + * + * Dan Williams + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * (C) Copyright 2004 Red Hat, Inc. + */ + +#include +#include +#include +#include +#include + + +#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager" + +#define NM_DBUS_PATH "/org/freedesktop/NetworkManager" +#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" + + +void get_nm_status (DBusConnection *connection) +{ + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusError error; + + message = dbus_message_new_method_call ("org.freedesktop.NetworkManager", + "/org/freedesktop/NetworkManager", + "org.freedesktop.NetworkManager", + "status"); + if (message == NULL) + { + fprintf (stderr, "Couldn't allocate the dbus message\n"); + return; + } + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (connection, message, -1, &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "%s raised:\n %s\n\n", error.name, error.message); + dbus_message_unref (message); + return; + } + + if (reply == NULL) + { + fprintf( stderr, "dbus reply message was NULL\n" ); + dbus_message_unref (message); + return; + } + + /* now analyze reply */ + dbus_message_iter_init (reply, &iter); + char *string; + string = dbus_message_iter_get_string (&iter); + if (!string) + { + fprintf (stderr, "NetworkManager returned a NULL status" ); + return; + } + + fprintf (stderr, "NM Status: '%s'\n", string ); + + dbus_message_unref (reply); + dbus_message_unref (message); +} + +/* + * dbus_filter + * + * Handles dbus messages from NetworkManager, exit our main loop if a device is active + */ +static DBusHandlerResult dbus_filter (DBusConnection *connection, DBusMessage *message, void *user_data) +{ + GMainLoop *loop = (GMainLoop *)user_data; + + if (loop && dbus_message_is_signal (message, NM_DBUS_INTERFACE, "DeviceNowActive")) + { + g_main_loop_quit (loop); + return (DBUS_HANDLER_RESULT_HANDLED); + } + + return (DBUS_HANDLER_RESULT_NOT_YET_HANDLED); +} + + + +/* + * dbus_init + * + * Initialize a connection to NetworkManager + */ +static DBusConnection *dbus_init (GMainLoop *loop) +{ + DBusConnection *connection = NULL; + DBusError error; + + /* connect to NetworkManager service on the system bus */ + dbus_error_init (&error); + connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); + if (connection == NULL) + { + fprintf (stderr, "dbus_init(): could not connect to the message bus. dbus says: '%s'\n", error.message); + dbus_error_free (&error); + return (NULL); + } + + dbus_connection_setup_with_g_main (connection, NULL); + + if (!dbus_connection_add_filter (connection, dbus_filter, (gpointer)loop, NULL)) + return (NULL); + + dbus_bus_add_match (connection, + "type='signal'," + "interface='" NM_DBUS_INTERFACE "'," + "sender='" NM_DBUS_SERVICE "'," + "path='" NM_DBUS_PATH "'", &error); + if (dbus_error_is_set (&error)) + return (NULL); + + return (connection); +} + + +int main( int argc, char *argv[] ) +{ + GMainLoop *loop; + DBusConnection *connection; + guint timeout; + + g_type_init (); + if (!g_thread_supported ()) + g_thread_init (NULL); + + loop = g_main_loop_new (NULL, FALSE); + + if (!(connection = dbus_init (loop))) + return (1); + + /* If NM doesn't get a connection within a reasonable amount of time, + * exit to let bootup continue. + */ + timeout = g_timeout_add (10000, g_main_loop_quit, loop); + + g_main_loop_run (loop); + + g_source_remove (timeout); + + return (0); +} diff --git a/initscript/NetworkManager b/initscript/NetworkManager index 79a8ac1653..a8a22af0e2 100755 --- a/initscript/NetworkManager +++ b/initscript/NetworkManager @@ -34,7 +34,7 @@ start() action $"Setting network parameters: " sysctl -e -p /etc/sysctl.conf echo -n $"Starting NetworkManager daemon: " daemon --check $servicename $processname - sleep 4 + NMLaunchHelper RETVAL=$? echo [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$servicename && echo `/sbin/pidof $processname` > $pidfile