summaryrefslogtreecommitdiff
path: root/telepathy-glib/run.c
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2007-04-19 17:35:17 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2007-04-19 17:35:17 +0000
commit05b3d77a6ceaf9142e0dee8bf52e7637d5823bdd (patch)
treeae7da2dc08fb4c3aa1c6b09ffa1c57d2d3adf24a /telepathy-glib/run.c
parent90720ee40eb30e2b1c9aa90501391d3a0a411250 (diff)
downloadtelepathy-glib-05b3d77a6ceaf9142e0dee8bf52e7637d5823bdd.tar.gz
Move contents of lib/ into root directory
20070419173517-53eee-d91a15d77882d6839193c1f77be4f88803b48f58.gz
Diffstat (limited to 'telepathy-glib/run.c')
-rw-r--r--telepathy-glib/run.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/telepathy-glib/run.c b/telepathy-glib/run.c
new file mode 100644
index 000000000..a594c95d6
--- /dev/null
+++ b/telepathy-glib/run.c
@@ -0,0 +1,242 @@
+/*
+ * run.c - entry point for telepathy-glib connection managers
+ * Copyright (C) 2005, 2007 Collabora Ltd.
+ * Copyright (C) 2005, 2007 Nokia Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * SECTION:run
+ * @title: Connection manager life cycle
+ * @short_description: entry point for telepathy-glib connection managers
+ *
+ * tp_run_connection_manager() provides a convenient entry point for
+ * telepathy-glib connection managers. It initializes most of the
+ * functionality the CM will need, constructs a connection manager object
+ * and lets it run.
+ *
+ * This function also manages the connection manager's lifetime - if there
+ * are no new connections for a while, it times out and exits.
+ */
+
+#include "config.h"
+
+#include <telepathy-glib/run.h>
+
+#include <dbus/dbus-glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "internal-debug.h"
+#include <telepathy-glib/base-connection-manager.h>
+#include <telepathy-glib/debug.h>
+#include <telepathy-glib/errors.h>
+
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif /* HAVE_EXECINFO_H */
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif /* HAVE_SIGNAL_H */
+
+static GMainLoop *mainloop = NULL;
+static TpBaseConnectionManager *manager = NULL;
+static gboolean connections_exist = FALSE;
+static guint timeout_id = 0;
+
+static gboolean
+kill_connection_manager (gpointer data)
+{
+#ifdef ENABLE_DEBUG
+ if (!_tp_debug_flag_is_set (TP_DEBUG_PERSIST) && !connections_exist)
+#else
+ if (!connections_exist)
+#endif
+ {
+ g_debug ("no connections, and timed out");
+ g_object_unref (manager);
+ g_main_loop_quit (mainloop);
+ }
+
+ timeout_id = 0;
+ return FALSE;
+}
+
+static void
+new_connection (TpBaseConnectionManager *conn,
+ gchar *bus_name,
+ gchar *object_path,
+ gchar *proto)
+{
+ connections_exist = TRUE;
+
+ if (0 != timeout_id)
+ {
+ g_source_remove (timeout_id);
+ }
+}
+
+#define DIE_TIME 5000
+
+static void
+no_more_connections (TpBaseConnectionManager *conn)
+{
+ connections_exist = FALSE;
+
+ if (0 != timeout_id)
+ {
+ g_source_remove (timeout_id);
+ }
+
+ timeout_id = g_timeout_add (DIE_TIME, kill_connection_manager, NULL);
+}
+
+#ifdef ENABLE_BACKTRACE
+static void
+print_backtrace (void)
+{
+#if defined (HAVE_BACKTRACE) && defined (HAVE_BACKTRACE_SYMBOLS_FD)
+ void *array[20];
+ size_t size;
+
+#define MSG "\n########## Backtrace (version " VERSION ") ##########\n"
+ write (STDERR_FILENO, MSG, strlen (MSG));
+#undef MSG
+
+ size = backtrace (array, 20);
+ backtrace_symbols_fd (array, size, STDERR_FILENO);
+#endif /* HAVE_BACKTRACE && HAVE_BACKTRACE_SYMBOLS_FD */
+}
+
+static void
+critical_handler (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ g_log_default_handler (log_domain, log_level, message, user_data);
+ print_backtrace ();
+}
+
+#ifdef HAVE_SIGNAL
+static void
+segv_handler (int sig)
+{
+#define MSG "caught SIGSEGV\n"
+ write (STDERR_FILENO, MSG, strlen (MSG));
+#undef MSG
+
+ print_backtrace ();
+ abort ();
+}
+#endif /* HAVE_SIGNAL */
+
+#endif /* ENABLE_BACKTRACE */
+
+static void
+add_signal_handlers (void)
+{
+#if defined (HAVE_SIGNAL) && defined (ENABLE_BACKTRACE)
+ signal (SIGSEGV, segv_handler);
+#endif /* HAVE_SIGNAL && ENABLE_BACKTRACE */
+}
+
+/**
+ * tp_run_connection_manager:
+ * @prog_name: The program name to be used in debug messages etc.
+ * @version: The program version
+ * @construct_cm: A function which will return the connection manager
+ * object
+ * @argc: The number of arguments passed to the program
+ * @argv: The arguments passed to the program
+ *
+ * Run the connection manager by initializing libraries, constructing
+ * a main loop, instantiating a connection manager and running the main
+ * loop. When this function returns, the program should exit.
+ *
+ * If the connection manager does not create a connection within a
+ * short arbitrary time (currently 5 seconds), either on startup or after
+ * the last open connection is disconnected, and the PERSIST debug
+ * flag is not set, return 0.
+ *
+ * If registering the connection manager on D-Bus fails, return 1.
+ *
+ * Returns: the status code with which the process should exit
+ */
+
+int
+tp_run_connection_manager (const char *prog_name,
+ const char *version,
+ TpBaseConnectionManager *(*construct_cm) (void),
+ int argc,
+ char **argv)
+{
+ GLogLevelFlags fatal_mask;
+
+ add_signal_handlers ();
+
+ g_type_init ();
+
+ g_set_prgname (prog_name);
+
+ fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
+ fatal_mask |= G_LOG_LEVEL_CRITICAL;
+ g_log_set_always_fatal (fatal_mask);
+
+#ifdef ENABLE_BACKTRACE
+ g_log_set_handler ("GLib-GObject",
+ G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR |
+ G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
+ critical_handler, NULL);
+ g_log_set_handler ("GLib",
+ G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR |
+ G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
+ critical_handler, NULL);
+ g_log_set_handler (NULL,
+ G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR |
+ G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
+ critical_handler, NULL);
+#endif /* ENABLE_BACKTRACE */
+
+ mainloop = g_main_loop_new (NULL, FALSE);
+
+ dbus_g_error_domain_register (TP_ERRORS,
+ "org.freedesktop.Telepathy.Error", TP_TYPE_ERROR);
+
+ manager = construct_cm ();
+
+ g_signal_connect (manager, "new-connection",
+ (GCallback) new_connection, NULL);
+
+ g_signal_connect (manager, "no-more-connections",
+ (GCallback) no_more_connections, NULL);
+
+ if (!tp_base_connection_manager_register (manager))
+ {
+ return 1;
+ }
+
+ g_debug ("started version %s (telepathy-glib version %s)", version,
+ VERSION);
+
+ timeout_id = g_timeout_add (DIE_TIME, kill_connection_manager, NULL);
+
+ g_main_loop_run (mainloop);
+
+ return 0;
+}