Fix reference counting for SilcServerEntry objects,
authorSkywing <skywing@valhallalegends.com>
Sat, 28 Jun 2008 04:44:03 +0000 (23:44 -0500)
committerKp <kp@valhallalegends.com>
Sat, 8 Nov 2008 23:03:55 +0000 (18:03 -0500)
analogous to the previous fixes for the broken
reference counting for SilcChannelEntry and
SilcClientEntry objects.

lib/silcclient/client.h
lib/silcclient/client_entry.c

index d66808dcef168e06473e7168104b18f97430ce43..542b6329fc1ef4bd6d9dce9a777bf93155d565c9 100644 (file)
@@ -101,6 +101,8 @@ typedef struct SilcServerEntryInternalStruct {
   SilcRwLock lock;                          /* Read/write lock */
   SilcUInt16 resolve_cmd_ident;                     /* Resolving identifier */
   SilcAtomic32 refcnt;                      /* Reference counter */
+  SilcAtomic32 deleted;     /* Flag indicating whether the server object is
+                                                                          already scheduled for deletion.*/
 } SilcServerEntryInternal;
 
 #endif /* CLIENT_H */
index 4664dbaa75f770446b457b8b7d830b67cab2d524..034a838e6261fed4db1355162fc834858b74d622 100644 (file)
@@ -2125,37 +2125,18 @@ SilcServerEntry silc_client_add_server(SilcClient client,
 SilcBool silc_client_del_server(SilcClient client, SilcClientConnection conn,
                                SilcServerEntry server)
 {
-  SilcIDCacheEntry id_cache;
-  SilcBool ret = TRUE;
-  char *namec;
-
   if (!server)
     return FALSE;
 
-  if (silc_atomic_sub_int32(&server->internal.refcnt, 1) > 0)
-    return FALSE;
-
-  SILC_LOG_DEBUG(("Deleting server %p", server));
-
-  silc_mutex_lock(conn->internal->lock);
-  if (silc_idcache_find_by_context(conn->internal->server_cache, server,
-                                  &id_cache)) {
-    namec = id_cache->name;
-    ret = silc_idcache_del_by_context(conn->internal->server_cache,
-                                     server, NULL);
-    silc_free(namec);
+  if (silc_atomic_sub_int32(&server->internal.deleted, 1) != 0)
+  {
+         SILC_LOG_DEBUG(("** WARNING ** Deleting a server twice %p", server));
+//       asm("int3");
+         return FALSE;
   }
-  silc_mutex_unlock(conn->internal->lock);
 
-  silc_free(server->server_name);
-  silc_free(server->server_info);
-  if (server->public_key)
-    silc_pkcs_public_key_free(server->public_key);
-  silc_atomic_uninit32(&server->internal.refcnt);
-  silc_rwlock_free(server->internal.lock);
-  silc_free(server);
-
-  return ret;
+  silc_client_unref_server(client, conn, server);
+  return TRUE;
 }
 
 /* Updates the `server_entry' with the new information sent as argument. */
@@ -2231,13 +2212,35 @@ SilcServerEntry silc_client_ref_server(SilcClient client,
 void silc_client_unref_server(SilcClient client, SilcClientConnection conn,
                              SilcServerEntry server_entry)
 {
-  if (server_entry) {
-    SILC_LOG_DEBUG(("Server %p refcnt %d->%d", server_entry,
-                   silc_atomic_get_int32(&server_entry->internal.refcnt),
-                   silc_atomic_get_int32(&server_entry->internal.refcnt)
-                   - 1));
-    silc_client_del_server(client, conn, server_entry);
+  SilcBool ret;
+  SilcIDCacheEntry id_cache;
+  char *namec;
+
+  if (!server_entry)
+    return;
+
+  if (silc_atomic_sub_int32(&server_entry->internal.refcnt, 1) > 0)
+    return;
+
+  SILC_LOG_DEBUG(("Deleting server %p", server_entry));
+
+  silc_mutex_lock(conn->internal->lock);
+  if (silc_idcache_find_by_context(conn->internal->server_cache, server_entry,
+                                  &id_cache)) {
+    namec = id_cache->name;
+    ret = silc_idcache_del_by_context(conn->internal->server_cache,
+                                     server_entry, NULL);
+    silc_free(namec);
   }
+  silc_mutex_unlock(conn->internal->lock);
+
+  silc_free(server_entry->server_name);
+  silc_free(server_entry->server_info);
+  if (server_entry->public_key)
+    silc_pkcs_public_key_free(server_entry->public_key);
+  silc_atomic_uninit32(&server_entry->internal.refcnt);
+  silc_rwlock_free(server_entry->internal.lock);
+  silc_free(server_entry);
 }
 
 /* Free server entry list */