]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Very very rarely, the avahi client becomes disconnected.
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Wed, 27 Sep 2023 09:36:28 +0000 (10:36 +0100)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Wed, 27 Sep 2023 09:36:28 +0000 (10:36 +0100)
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

index c154ec60a7d7e74ce9fec344d3b3bf197eee30fd..2204592ab982b0a6e2cb1d529c5c06bbad944952 100644 (file)
@@ -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 {