From 04e3f891301f993154e8e84b7f89e53d3d693b77 Mon Sep 17 00:00:00 2001 From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Wed, 27 Sep 2023 10:36:28 +0100 Subject: [PATCH] Very very rarely, the avahi client becomes disconnected. This usually means there are problems in the system as a whole rahter than with Shairport Sync. However, Shairport Sync was not cleaning up properly before deleting the now-disconnected avahi client and creating a new one in an attempt to reconnect. That caused Shairport Sync to crash even if the new avahi client was created successfully. So this commit has code to delete the avahi group and broswer callback before deleting the disconnected avahi client. --- mdns_avahi.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/mdns_avahi.c b/mdns_avahi.c index c154ec60..2204592a 100644 --- a/mdns_avahi.c +++ b/mdns_avahi.c @@ -206,7 +206,7 @@ static void egroup_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, debug(2, "avahi: service name collision, renaming service to '%s'", service_name); - /* And recreate the services */ + /* And try to recreate the services */ register_service(avahi_entry_group_get_client(g)); break; } @@ -230,6 +230,15 @@ static void egroup_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, } } +static int deregister_service(AVAHI_GCC_UNUSED AvahiClient *c) { + int response = 0; + if (group != NULL) { + response = avahi_entry_group_free(group); + group = NULL; + } + return response; +} + static void register_service(AvahiClient *c) { if (!group) group = avahi_entry_group_new(c, egroup_callback, NULL); @@ -293,21 +302,26 @@ static void client_callback(AvahiClient *c, AvahiClientState state, case AVAHI_CLIENT_FAILURE: err = avahi_client_errno(c); - debug(1, "avahi: client failure: %s", avahi_strerror(err)); - if (err == AVAHI_ERR_DISCONNECTED) { - debug(1, "avahi client -- we have been disconnected, so let's reconnect."); - /* We have been disconnected, so lets reconnect */ - if (c) - avahi_client_free(c); - else - debug(1, "Attempt to free NULL avahi client"); - c = NULL; - group = NULL; - + debug(1, "avahi client disconnected -- reconnection attempted."); + if (c) { + // it seems that the avahi_threaded_poll thread is still running and locked here + deregister_service(c); // delete the group + dacp_browser_struct *dbs = &private_dbs; + if (dbs->service_browser) { + int rc = avahi_service_browser_free(dbs->service_browser); // delete the service browser + if (rc != 0) + debug(1, + "Error %d freeing the Avahi service browser after the Avahi client has been " + "disconnected.", + rc); + dbs->service_browser = NULL; + } + avahi_client_free(c); // delete the client + } if (!(client = avahi_client_new(avahi_threaded_poll_get(tpoll), AVAHI_CLIENT_NO_FAIL, client_callback, userdata, &err))) { - warn("avahi: failed to create client object: %s", avahi_strerror(err)); + warn("avahi: failed to create a replacement client object: %s", avahi_strerror(err)); avahi_threaded_poll_quit(tpoll); } } else {