From 64ab9be453f31b55e35ad5cad8102a9e45244a8c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 18 Jun 2005 23:22:20 +0000 Subject: * fix memory handling when reading configuration files * implement signal handling in daemon * correctly increase reference counter for main contexts when running g_main_context_default() git-svn-id: file:///home/lennart/svn/public/avahi/trunk@128 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- avahi-core/netlink.c | 4 +- avahi-core/server.c | 5 +- avahi-daemon/main.c | 130 ++++++++++++++++++++++++++++++++++------- avahi-daemon/simple-protocol.c | 32 +++++----- avahi-daemon/static-services.c | 2 +- 5 files changed, 131 insertions(+), 42 deletions(-) diff --git a/avahi-core/netlink.c b/avahi-core/netlink.c index 50ddf5c..ff88b91 100644 --- a/avahi-core/netlink.c +++ b/avahi-core/netlink.c @@ -120,7 +120,6 @@ AvahiNetlink *avahi_netlink_new(GMainContext *context, gint priority, guint32 gr NULL }; - g_assert(context); g_assert(cb); if ((fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { @@ -140,8 +139,7 @@ AvahiNetlink *avahi_netlink_new(GMainContext *context, gint priority, guint32 gr } nl = g_new(AvahiNetlink, 1); - nl->context = context; - g_main_context_ref(context); + g_main_context_ref(nl->context = context ? context : g_main_context_default()); nl->fd = fd; nl->seq = 0; nl->callback = cb; diff --git a/avahi-core/server.c b/avahi-core/server.c index 0c00658..d03a284 100644 --- a/avahi-core/server.c +++ b/avahi-core/server.c @@ -1275,10 +1275,7 @@ AvahiServer *avahi_server_new(GMainContext *c, const AvahiServerConfig *sc, Avah s->fd_legacy_unicast_ipv4 = s->fd_ipv4 >= 0 && s->config.enable_reflector ? avahi_open_legacy_unicast_socket_ipv4() : -1; s->fd_legacy_unicast_ipv6 = s->fd_ipv6 >= 0 && s->config.enable_reflector ? avahi_open_legacy_unicast_socket_ipv6() : -1; - if (c) - g_main_context_ref(s->context = c); - else - s->context = g_main_context_default(); + g_main_context_ref(c->context = c ? c : g_main_context_default()); /* Prepare IO source registration */ s->source = g_source_new(&source_funcs, sizeof(GSource) + sizeof(AvahiServer*)); diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c index 4373f9a..0d862ea 100644 --- a/avahi-daemon/main.c +++ b/avahi-daemon/main.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -143,7 +145,7 @@ static gint load_config_file(DaemonConfig *config) { int r = -1; GKeyFile *f = NULL; GError *err = NULL; - gchar **groups = NULL, **g, **keys = NULL; + gchar **groups = NULL, **g, **keys = NULL, *v = NULL; g_assert(config); @@ -163,27 +165,38 @@ static gint load_config_file(DaemonConfig *config) { keys = g_key_file_get_keys(f, *g, NULL, NULL); for (k = keys; *k; k++) { + + v = g_key_file_get_value(f, *g, *k, NULL); + if (g_strcasecmp(*k, "host-name") == 0) { g_free(config->server_config.host_name); - config->server_config.host_name = g_strdup(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.host_name = v; + v = NULL; } else if (g_strcasecmp(*k, "domain-name") == 0) { g_free(config->server_config.domain_name); - config->server_config.domain_name = g_strdup(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.domain_name = v; + v = NULL; } else if (g_strcasecmp(*k, "use-ipv4") == 0) - config->server_config.use_ipv4 = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.use_ipv4 = is_yes(v); else if (g_strcasecmp(*k, "use-ipv6") == 0) - config->server_config.use_ipv6 = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.use_ipv6 = is_yes(v); else if (g_strcasecmp(*k, "check-response-ttl") == 0) - config->server_config.check_response_ttl = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.check_response_ttl = is_yes(v); else if (g_strcasecmp(*k, "use-iff-running") == 0) - config->server_config.use_iff_running = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.use_iff_running = is_yes(v); else if (g_strcasecmp(*k, "enable-dbus") == 0) - config->enable_dbus = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->enable_dbus = is_yes(v); else { fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g); goto finish; } + + g_free(v); + v = NULL; } + + g_strfreev(keys); + keys = NULL; } else if (g_strcasecmp(*g, "publish") == 0) { gchar **k; @@ -191,36 +204,54 @@ static gint load_config_file(DaemonConfig *config) { keys = g_key_file_get_keys(f, *g, NULL, NULL); for (k = keys; *k; k++) { + + v = g_key_file_get_string(f, *g, *k, NULL); + if (g_strcasecmp(*k, "publish-addresses") == 0) - config->server_config.publish_addresses = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.publish_addresses = is_yes(v); else if (g_strcasecmp(*k, "publish-hinfo") == 0) - config->server_config.publish_hinfo = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.publish_hinfo = is_yes(v); else if (g_strcasecmp(*k, "publish-workstation") == 0) - config->server_config.publish_workstation = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.publish_workstation = is_yes(v); else if (g_strcasecmp(*k, "publish-domain") == 0) - config->server_config.publish_domain = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.publish_domain = is_yes(v); else { fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g); goto finish; } + + g_free(v); + v = NULL; } + g_strfreev(keys); + keys = NULL; + } else if (g_strcasecmp(*g, "reflector") == 0) { gchar **k; keys = g_key_file_get_keys(f, *g, NULL, NULL); for (k = keys; *k; k++) { + + v = g_key_file_get_string(f, *g, *k, NULL); + if (g_strcasecmp(*k, "enable-reflector") == 0) - config->server_config.enable_reflector = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.enable_reflector = is_yes(v); else if (g_strcasecmp(*k, "reflect-ipv") == 0) - config->server_config.reflect_ipv = is_yes(g_key_file_get_string(f, *g, *k, NULL)); + config->server_config.reflect_ipv = is_yes(v); else { fprintf(stderr, "Invalid configuration key \"%s\" in group \"%s\"\n", *k, *g); goto finish; } + + g_free(v); + v = NULL; } + g_strfreev(keys); + keys = NULL; + } else { fprintf(stderr, "Invalid configuration file group \"%s\".\n", *g); goto finish; @@ -233,6 +264,7 @@ finish: g_strfreev(groups); g_strfreev(keys); + g_free(v); if (err) g_error_free (err); @@ -259,13 +291,61 @@ static void log_function(AvahiLogLevel level, const gchar *txt) { daemon_log(log_level_map[level], "%s", txt); } +static gboolean signal_callback(GIOChannel *source, GIOCondition condition, gpointer data) { + gint sig; + g_assert(source); + + if ((sig = daemon_signal_next()) <= 0) { + avahi_log_error("daemon_signal_next() failed"); + return FALSE; + } + + switch (sig) { + case SIGINT: + case SIGQUIT: + case SIGTERM: + avahi_log_info( + "Got %s, quitting.", + sig == SIGINT ? "SIGINT" : + (sig == SIGQUIT ? "SIGQUIT" : "SIGTERM")); + g_main_loop_quit((GMainLoop*) data); + break; + + case SIGHUP: + avahi_log_info("Got SIGHUP, reloading."); + static_service_load(); + break; + + default: + avahi_log_warn("Got spurious signal, ignoring."); + break; + } + + return TRUE; +} + static gint run_server(DaemonConfig *config) { GMainLoop *loop = NULL; gint r = -1; + GIOChannel *io = NULL; + guint watch_id = (guint) -1; g_assert(config); loop = g_main_loop_new(NULL, FALSE); + + if (daemon_signal_init(SIGINT, SIGQUIT, SIGHUP, SIGTERM, 0) < 0) { + avahi_log_error("Could not register signal handlers (%s).", strerror(errno)); + goto finish; + } + + if (!(io = g_io_channel_unix_new(daemon_signal_fd()))) { + avahi_log_error( "Failed to create signal io channel."); + goto finish; + } + + g_io_channel_set_close_on_unref(io, FALSE); + g_io_add_watch(io, G_IO_IN, signal_callback, loop); if (simple_protocol_setup(NULL) < 0) goto finish; @@ -285,9 +365,8 @@ static gint run_server(DaemonConfig *config) { daemon_retval_send(0); r = 0; } - - g_main_loop_run(loop); + g_main_loop_run(loop); finish: @@ -303,12 +382,21 @@ finish: if (avahi_server) avahi_server_free(avahi_server); + + daemon_signal_done(); + + if (watch_id != (guint) -1) + g_source_remove(watch_id); + if (io) + g_io_channel_unref(io); + + if (loop) g_main_loop_unref(loop); if (r != 0 && config->daemonize) - daemon_retval_send(0); + daemon_retval_send(1); return r; } @@ -348,7 +436,7 @@ int main(int argc, char *argv[]) { } else if (config.command == DAEMON_KILL) { if (daemon_pid_file_kill_wait(SIGTERM, 5) < 0) { - avahi_log_warn("Failed to kill daemon"); + avahi_log_warn("Failed to kill daemon: %s", strerror(errno)); goto finish; } @@ -385,8 +473,10 @@ int main(int argc, char *argv[]) { } if (daemon_pid_file_create() < 0) { - avahi_log_error("Failed to create PID file."); - daemon_retval_send(1); + avahi_log_error("Failed to create PID file: %s", strerror(errno)); + + if (config.daemonize) + daemon_retval_send(1); goto finish; } else wrote_pid_file = TRUE; diff --git a/avahi-daemon/simple-protocol.c b/avahi-daemon/simple-protocol.c index 91a8287..6eaef99 100644 --- a/avahi-daemon/simple-protocol.c +++ b/avahi-daemon/simple-protocol.c @@ -34,6 +34,7 @@ #include #include +#include #include "simple-protocol.h" #include "main.h" @@ -80,6 +81,7 @@ struct Server { AVAHI_LLIST_HEAD(Client, clients); guint n_clients; + gboolean bind_successful; }; static Server *server = NULL; @@ -264,7 +266,7 @@ static void client_work(Client *c) { if ((r = read(c->fd, c->inbuf + c->inbuf_length, sizeof(c->inbuf) - c->inbuf_length)) <= 0) { if (r < 0) - g_warning("read(): %s", strerror(errno)); + avahi_log_warn("read(): %s", strerror(errno)); client_free(c); return; } @@ -279,7 +281,7 @@ static void client_work(Client *c) { ssize_t r; if ((r = write(c->fd, c->outbuf, c->outbuf_length)) < 0) { - g_warning("write(): %s", strerror(errno)); + avahi_log_warn("write(): %s", strerror(errno)); client_free(c); return; } @@ -337,7 +339,7 @@ static gboolean dispatch_func(GSource *source, GSourceFunc callback, gpointer us gint fd; if ((fd = accept(s->fd, NULL, NULL)) < 0) - g_warning("accept(): %s", strerror(errno)); + avahi_log_warn("accept(): %s", strerror(errno)); else client_new(s, fd); } else if (s->poll_fd.revents) @@ -368,23 +370,21 @@ int simple_protocol_setup(GMainContext *c) { g_assert(!server); server = (Server*) g_source_new(&source_funcs, sizeof(Server)); + server->bind_successful = FALSE; server->fd = -1; AVAHI_LLIST_HEAD_INIT(Client, server->clients); - if (c) - g_main_context_ref(server->context = c); - else - server->context = g_main_context_default(); + g_main_context_ref(server->context = (c ? c : g_main_context_default())); server->clients = NULL; u = umask(0000); if (mkdir(UNIX_SOCKET_PATH, 0755) < 0 && errno != EEXIST) { - g_warning("mkdir(): %s", strerror(errno)); + avahi_log_warn("mkdir(): %s", strerror(errno)); goto fail; } if ((server->fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) { - g_warning("socket(PF_LOCAL, SOCK_STREAM, 0): %s", strerror(errno)); + avahi_log_warn("socket(PF_LOCAL, SOCK_STREAM, 0): %s", strerror(errno)); goto fail; } @@ -393,12 +393,14 @@ int simple_protocol_setup(GMainContext *c) { strncpy(sa.sun_path, UNIX_SOCKET, sizeof(sa.sun_path)-1); if (bind(server->fd, &sa, sizeof(sa)) < 0) { - g_warning("bind(): %s", strerror(errno)); + avahi_log_warn("bind(): %s", strerror(errno)); goto fail; } + + server->bind_successful = TRUE; if (listen(server->fd, 2) < 0) { - g_warning("listen(): %s", strerror(errno)); + avahi_log_warn("listen(): %s", strerror(errno)); goto fail; } @@ -427,13 +429,15 @@ void simple_protocol_shutdown(void) { while (server->clients) client_free(server->clients); + + if (server->bind_successful) + unlink(UNIX_SOCKET); - if (server->fd >= 0) { - unlink(UNIX_SOCKET_PATH); + if (server->fd >= 0) close(server->fd); - } g_main_context_unref(server->context); + g_source_destroy(&server->source); g_source_unref(&server->source); diff --git a/avahi-daemon/static-services.c b/avahi-daemon/static-services.c index 89e8122..8148de4 100644 --- a/avahi-daemon/static-services.c +++ b/avahi-daemon/static-services.c @@ -211,7 +211,7 @@ static void add_static_service_group_to_server(StaticServiceGroup *g) { -1, AF_UNSPEC, s->type, g->chosen_name, s->domain_name, s->host_name, s->port, - s->txt_records) < 0) { + avahi_string_list_copy(s->txt_records)) < 0) { g_message("Failed to add service '%s' of type '%s', ignoring service group (%s)", g->chosen_name, s->type, g->filename); remove_static_service_group_from_server(g); return; -- cgit