[xiph-cvs] cvs commit: icecast/src cfgfile.h connection.c global.c global.h slave.c slave.h source.c
Karl Heyes
karl at xiph.org
Thu Feb 19 12:28:22 PST 2004
karl 04/02/19 15:28:21
Modified: src cfgfile.h connection.c global.c global.h slave.c
slave.h source.c
Log:
Make the slave thread reserve relay mountpoints, and prevent reconnection
when a relay is currently active.
Revision Changes Path
1.7 +0 -9 icecast/src/cfgfile.h
Index: cfgfile.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/cfgfile.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- cfgfile.h 29 Jan 2004 01:02:06 -0000 1.6
+++ cfgfile.h 19 Feb 2004 20:28:20 -0000 1.7
@@ -32,15 +32,6 @@
struct ice_config_dir_tag *next;
} ice_config_dir_t;
-typedef struct _relay_server {
- char *server;
- int port;
- char *mount;
- char *localmount;
- int mp3metadata;
- struct _relay_server *next;
-} relay_server;
-
typedef struct _config_options {
char *name;
char *value;
<p><p>1.87 +21 -4 icecast/src/connection.c
Index: connection.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/connection.c,v
retrieving revision 1.86
retrieving revision 1.87
diff -u -r1.86 -r1.87
--- connection.c 19 Feb 2004 16:32:23 -0000 1.86
+++ connection.c 19 Feb 2004 20:28:21 -0000 1.87
@@ -479,6 +479,7 @@
global.sources++;
global_unlock();
+ stats_event_inc(NULL, "sources");
/* for relays, we don't yet have a client, however we do require one
* to retrieve the stream from. This is created here, quite late,
@@ -578,10 +579,28 @@
}
config_release_config();
+ /* we need to add this source into the tree but fail if this mountpoint
+ * already exists
+ */
+ avl_tree_wlock(global.source_tree);
+ if (source_find_mount_raw (mount) != NULL)
+ {
+ avl_tree_unlock(global.source_tree);
+ global_lock();
+ global.sources--;
+ global_unlock();
+ stats_event_dec(NULL, "sources");
+ INFO1("source \"%s\" already in use", mount);
+ client_send_404 (client, "Mountpoint in use");
+ return 0;
+ }
+ avl_insert(global.source_tree, (void *)source);
+ avl_tree_unlock(global.source_tree);
+
source->send_return = 1;
source->shutdown_rwlock = &_source_shutdown_rwlock;
sock_set_blocking(con->sock, SOCK_NONBLOCK);
- thread_create("Source Thread", source_main, (void *)source, THREAD_DETACHED);
+ thread_create("Source Thread", source_client_thread, (void *)source, THREAD_DETACHED);
return 1;
fail:
@@ -775,9 +794,7 @@
}
avl_tree_unlock(global.source_tree);
- if (!connection_create_source(client, con, parser, uri)) {
- client_send_404(client, "Mountpoint in use");
- }
+ connection_create_source(client, con, parser, uri);
}
static void _handle_stats_request(connection_t *con,
<p><p>1.12 +3 -1 icecast/src/global.c
Index: global.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/global.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -r1.11 -r1.12
--- global.c 29 Jan 2004 01:02:06 -0000 1.11
+++ global.c 19 Feb 2004 20:28:21 -0000 1.12
@@ -37,6 +37,8 @@
{
memset(global.serversock, 0, sizeof(int)*MAX_LISTEN_SOCKETS);
global.server_sockets = 0;
+ global.relays = NULL;
+ global.master_relays = NULL;
global.running = 0;
global.clients = 0;
global.sources = 0;
@@ -47,7 +49,7 @@
void global_shutdown(void)
{
thread_mutex_destroy(&_global_mutex);
- avl_tree_free(global.source_tree, source_free_source);
+ avl_tree_free(global.source_tree, NULL);
}
void global_lock(void)
<p><p>1.13 +5 -0 icecast/src/global.h
Index: global.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/global.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- global.h 29 Jan 2004 01:02:06 -0000 1.12
+++ global.h 19 Feb 2004 20:28:21 -0000 1.13
@@ -23,6 +23,7 @@
#define MAX_LISTEN_SOCKETS 10
#include "thread/thread.h"
+#include "slave.h"
typedef struct ice_global_tag
{
@@ -36,6 +37,10 @@
int schedule_config_reread;
avl_tree *source_tree;
+ /* for locally defined relays */
+ struct _relay_server *relays;
+ /* relays retrieved from master */
+ struct _relay_server *master_relays;
cond_t shutdown_cond;
} ice_global_t;
<p><p>1.33 +339 -150 icecast/src/slave.c
Index: slave.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/slave.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- slave.c 2 Feb 2004 19:22:11 -0000 1.32
+++ slave.c 19 Feb 2004 20:28:21 -0000 1.33
@@ -61,8 +61,53 @@
static void *_slave_thread(void *arg);
thread_type *_slave_thread_id;
-static int _initialized = 0;
-static unsigned max_interval = 0;
+static int slave_running = 0;
+static int max_interval = 0;
+
+relay_server *relay_free (relay_server *relay)
+{
+ relay_server *next = relay->next;
+ DEBUG1("freeing relay %s", relay->localmount);
+ if (relay->source)
+ source_free_source (relay->source);
+ xmlFree (relay->server);
+ xmlFree (relay->mount);
+ xmlFree (relay->localmount);
+ xmlFree (relay);
+ return next;
+}
+
+
+relay_server *relay_copy (relay_server *r)
+{
+ relay_server *copy = calloc (1, sizeof (relay_server));
+
+ if (copy)
+ {
+ copy->server = xmlStrdup (r->server);
+ copy->mount = xmlStrdup (r->mount);
+ copy->localmount = xmlStrdup (r->localmount);
+ copy->port = r->port;
+ copy->mp3metadata = r->mp3metadata;
+ }
+ return copy;
+}
+
+
+static void *_relay_thread (void *arg)
+{
+ relay_server *relay = arg;
+
+ relay->running = 1;
+
+ source_main (relay->source);
+
+ relay->running = 0;
+ if (relay->cleanup)
+ relay_free (relay);
+
+ return NULL;
+}
void slave_recheck (void)
@@ -71,189 +116,333 @@
}
-void slave_initialize(void) {
- ice_config_t *config;
- if (_initialized) return;
-
- config = config_get_config();
- /* Don't create a slave thread if it isn't configured */
- if (config->master_server == NULL &&
- config->relay == NULL)
- {
- config_release_config();
+void slave_initialize(void)
+{
+ if (slave_running)
return;
- }
- config_release_config();
- _initialized = 1;
+ slave_running = 1;
_slave_thread_id = thread_create("Slave Thread", _slave_thread, NULL, THREAD_ATTACHED);
}
-void slave_shutdown(void) {
- if (!_initialized) return;
- _initialized = 0;
- thread_join(_slave_thread_id);
+
+void slave_shutdown(void)
+{
+ relay_server *relay;
+
+ if (!slave_running)
+ return;
+ slave_running = 0;
+ thread_join (_slave_thread_id);
+
+ relay = global.relays;
+ while (relay)
+ relay = relay_free (relay);
+ global.relays = NULL;
+
+ relay = global.master_relays;
+ while (relay)
+ relay = relay_free (relay);
+ global.master_relays = NULL;
}
-static void create_relay_stream(char *server, int port,
- char *remotemount, char *localmount, int mp3)
+
+/* This does the actual connection for a relay. A thread is
+ * started off if a connection can be acquired
+ */
+static void start_relay_stream (relay_server *relay)
{
- sock_t streamsock;
+ sock_t streamsock = SOCK_ERROR;
+ source_t *src = relay->source;
+ http_parser_t *parser = NULL;
+ connection_t *con=NULL;
char header[4096];
- connection_t *con;
- http_parser_t *parser;
- client_t *client;
-
- if(!localmount)
- localmount = remotemount;
-
- DEBUG1("Adding source at mountpoint \"%s\"", localmount);
-
- streamsock = sock_connect_wto(server, port, 0);
- if (streamsock == SOCK_ERROR) {
- WARN2("Failed to relay stream from master server, couldn't connect to http://%s:%d", server, port);
- return;
- }
- con = create_connection(streamsock, -1, NULL);
- /* At this point we may not know if we are relaying a mp3 or vorbis stream,
- * so lets send in the icy-metadata header just in case, it's harmless in
- * the vorbis case. If we don't send in this header then relay will not
- * have mp3 metadata.
- */
- sock_write(streamsock, "GET %s HTTP/1.0\r\n"
- "User-Agent: " ICECAST_VERSION_STRING "\r\n"
- "Icy-MetaData: 1\r\n"
- "\r\n",
- remotemount);
- memset(header, 0, sizeof(header));
- if (util_read_header(con->sock, header, 4096) == 0) {
- WARN0("Header read failed");
- connection_close(con);
- return;
- }
- parser = httpp_create_parser();
- httpp_initialize(parser, NULL);
- if(!httpp_parse_response(parser, header, strlen(header), localmount)) {
- if(httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE)) {
- ERROR1("Error parsing relay request: %s",
- httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE));
+
+ INFO1("Starting relayed source at mountpoint \"%s\"", relay->localmount);
+ do
+ {
+ streamsock = sock_connect_wto (relay->server, relay->port, 30);
+ if (streamsock == SOCK_ERROR)
+ {
+ WARN3("Failed to relay stream from master server, couldn't connect to http://%s:%d%s",
+ relay->server, relay->port, relay->mount);
+ break;
}
- else
+ con = create_connection (streamsock, -1, NULL);
+
+ /* At this point we may not know if we are relaying an mp3 or vorbis
+ * stream, but only send the icy-metadata header if the relay details
+ * state so (the typical case). It's harmless in the vorbis case. If
+ * we don't send in this header then relay will not have mp3 metadata.
+ */
+ sock_write(streamsock, "GET %s HTTP/1.0\r\n"
+ "User-Agent: " ICECAST_VERSION_STRING "\r\n"
+ "%s"
+ "\r\n",
+ relay->mount, relay->mp3metadata?"Icy-MetaData: 1\r\n":"");
+ memset (header, 0, sizeof(header));
+ if (util_read_header (con->sock, header, 4096) == 0)
+ {
+ WARN0("Header read failed");
+ break;
+ }
+ parser = httpp_create_parser();
+ httpp_initialize (parser, NULL);
+ if (! httpp_parse_response (parser, header, strlen(header), relay->localmount))
+ {
ERROR0("Error parsing relay request");
- connection_close(con);
- httpp_destroy(parser);
+ break;
+ }
+ if (httpp_getvar (parser, HTTPP_VAR_ERROR_MESSAGE))
+ {
+ ERROR1("Error from relay request: %s", httpp_getvar(parser, HTTPP_VAR_ERROR_MESSAGE));
+ break;
+ }
+ src->parser = parser;
+ src->con = con;
+ if (connection_complete_source (src) < 0)
+ {
+ DEBUG0("Failed to complete source initialisation");
+ break;
+ }
+ thread_create ("Relay Thread", _relay_thread, relay, THREAD_DETACHED);
+
return;
+ } while (0);
+
+ if (con == NULL && streamsock != SOCK_ERROR)
+ sock_close (streamsock);
+ if (con)
+ connection_close (con);
+ src->con = NULL;
+ if (parser)
+ httpp_destroy (parser);
+ src->parser = NULL;
+}
+
+
+/* wrapper for starting the provided relay stream */
+static void check_relay_stream (relay_server *relay)
+{
+ if (relay->source == NULL)
+ {
+ /* new relay, reserve the name */
+ DEBUG1("Adding relay source at mountpoint \"%s\"", relay->localmount);
+ relay->source = source_reserve (relay->localmount);
+ }
+ if (relay->source && !relay->running)
+ {
+ start_relay_stream (relay);
}
+}
+
+
+/* go through updated looking for relays that are different configured. The
+ * returned list contains relays that should be kept running, current contains
+ * the list of relays to shutdown
+ */
+static relay_server *
+update_relay_set (relay_server **current, relay_server *updated)
+{
+ relay_server *relay = updated;
+ relay_server *existing_relay, **existing_p;
+ relay_server *new_list = NULL;
- client = client_create(con, parser);
- if (!connection_create_source(client, con, parser,
- httpp_getvar(parser, HTTPP_VAR_URI))) {
- DEBUG0("Failed to create source");
- client_destroy(client);
+ while (relay)
+ {
+ existing_relay = *current;
+ existing_p = current;
+
+ while (existing_relay)
+ {
+ if (strcmp (relay->localmount, existing_relay->localmount) == 0)
+ break;
+ existing_p = &existing_relay->next;
+ existing_relay = existing_relay->next;
+ }
+ if (existing_relay == NULL)
+ {
+ /* new one, copy and insert */
+ existing_relay = relay_copy (relay);
+ }
+ else
+ {
+ *existing_p = existing_relay->next;
+ }
+ existing_relay->next = new_list;
+ new_list = existing_relay;
+ relay = relay->next;
}
+ return new_list;
+}
- return;
+
+/* update the relay_list with entries from new_relay_list. Any new relays
+ * are added to the list, and any not listed in the provided new_relay_list
+ * get marked for shutting down, just in case they are not shutting down by
+ * themselves
+ */
+static void
+update_relays (relay_server **relay_list, relay_server *new_relay_list)
+{
+ relay_server *relay, *current;
+
+ current = update_relay_set (relay_list, new_relay_list);
+
+ /* ok whats left, lets make sure they shut down */
+ relay = *relay_list;
+ while (relay)
+ {
+ relay->cleanup = 1;
+ if (relay->source)
+ {
+ if (relay->source->running)
+ DEBUG1 ("requested %s to shut down", relay->source->mount);
+ relay->source->running = 0;
+ relay = relay->next;
+ }
+ else
+ relay = relay_free (relay);
+ }
+ /* re-assign new set */
+ *relay_list = current;
}
-static void *_slave_thread(void *arg) {
+
+static int update_from_master(ice_config_t *config)
+{
+ char *master = NULL, *password = NULL, *username= NULL;
+ int port;
sock_t mastersock;
+ int ret = 0;
char buf[256];
- unsigned interval = 0;
- char *authheader, *data;
- int len;
- char *username = "relay";
- relay_server *relay;
- ice_config_t *config;
+ do
+ {
+ char *authheader, *data;
+ relay_server *relays = NULL, *relay;
+ int len, count = 1;
+
+ username = strdup ("relay");
+ if (config->master_password)
+ password = strdup (config->master_password);
+
+ if (config->master_server)
+ master = strdup (config->master_server);
+
+ port = config->master_server_port;
+
+ if (password == NULL || master == NULL || port == 0)
+ break;
+ ret = 1;
+ config_release_config();
+ mastersock = sock_connect_wto (master, port, 0);
- while (_initialized) {
- if (max_interval > ++interval) {
- thread_sleep(1000000);
- continue;
+ if (mastersock == SOCK_ERROR)
+ {
+ WARN0("Relay slave failed to contact master server to fetch stream list");
+ break;
}
- else {
- /* In case it's been reconfigured */
- config = config_get_config();
- max_interval = config->master_update_interval;
- interval = 0;
+ len = strlen(username) + strlen(password) + 1;
+ authheader = malloc(len+1);
+ strcpy(authheader, username);
+ strcat(authheader, ":");
+ strcat(authheader, password);
+ data = util_base64_encode(authheader);
+ sock_write (mastersock,
+ "GET /admin/streamlist.txt HTTP/1.0\r\n"
+ "Authorization: Basic %s\r\n"
+ "\r\n", data);
+ free(authheader);
+ free(data);
+
+ while (sock_read_line(mastersock, buf, sizeof(buf)))
+ {
+ if (!strlen(buf))
+ break;
}
-
- if(config->master_server != NULL) {
- char *server = strdup (config->master_server);
- int port = config->master_server_port;
- char *password = NULL;
- if (config->master_password != NULL)
- password = strdup (config->master_password);
- else
- password = strdup (config->source_password);
- config_release_config();
-
- mastersock = sock_connect_wto(server, port, 0);
-
- if (mastersock == SOCK_ERROR) {
- WARN0("Relay slave failed to contact master server to fetch stream list");
- free (server);
- free (password);
+ while (sock_read_line(mastersock, buf, sizeof(buf)))
+ {
+ relay_server *r;
+ if (!strlen(buf))
continue;
+ DEBUG2 ("read %d from master \"%s\"", count++, buf);
+ r = calloc (1, sizeof (relay_server));
+ if (r)
+ {
+ r->server = xmlStrdup (master);
+ r->port = port;
+ r->mount = xmlStrdup (buf);
+ r->localmount = xmlStrdup (buf);
+ r->mp3metadata = 1;
+ r->next = relays;
+ relays = r;
}
-
- len = strlen(username) + strlen(password) + 1;
- authheader = malloc(len+1);
- strcpy(authheader, username);
- strcat(authheader, ":");
- strcat(authheader, password);
- data = util_base64_encode(authheader);
- sock_write(mastersock,
- "GET /admin/streamlist.txt HTTP/1.0\r\n"
- "Authorization: Basic %s\r\n"
- "\r\n", data);
- free(authheader);
- free(data);
- while (sock_read_line(mastersock, buf, sizeof(buf))) {
- if(!strlen(buf))
- break;
- }
-
- while (sock_read_line(mastersock, buf, sizeof(buf))) {
- avl_tree_rlock(global.source_tree);
- if (!source_find_mount(buf)) {
- avl_tree_unlock(global.source_tree);
-
- create_relay_stream(server, port, buf, NULL, 0);
- }
- else
- avl_tree_unlock(global.source_tree);
- }
- free (server);
- free (password);
- sock_close(mastersock);
}
- else {
- config_release_config();
+ sock_close (mastersock);
+
+ update_relays (&global.master_relays, relays);
+ /* start any inactive relays */
+ relay = global.master_relays;
+ while (relay)
+ {
+ check_relay_stream (relay);
+ relay = relay->next;
}
+ relay = relays;
+ while (relay)
+ relay = relay_free (relay);
+ } while(0);
+
+ if (master)
+ free (master);
+ if (username)
+ free (username);
+ if (password)
+ free (password);
+
+ return ret;
+}
+
+
+static void *_slave_thread(void *arg)
+{
+ ice_config_t *config;
+ relay_server *relay;
+ unsigned interval = 0;
- /* And now, we process the individual mounts... */
+ while (slave_running)
+ {
+ thread_sleep (1000000);
+ if (max_interval > ++interval)
+ continue;
+
+ interval = 0;
config = config_get_config();
- relay = config->relay;
- thread_mutex_lock(&(config_locks()->relay_lock));
- config_release_config();
- while(relay) {
- avl_tree_rlock(global.source_tree);
- if(!source_find_mount_raw(relay->localmount)) {
- avl_tree_unlock(global.source_tree);
+ max_interval = config->master_update_interval;
- create_relay_stream(relay->server, relay->port, relay->mount,
- relay->localmount, relay->mp3metadata);
- }
- else
- avl_tree_unlock(global.source_tree);
+ /* the connection could time some time, so the lock can drop */
+ if (update_from_master (config))
+ config = config_get_config();
+
+ thread_mutex_lock (&(config_locks()->relay_lock));
+
+ update_relays (&global.relays, config->relay);
+
+ config_release_config();
+
+ /* start any inactive relays */
+ relay = global.relays;
+ while (relay)
+ {
+ check_relay_stream (relay);
relay = relay->next;
}
-
- thread_mutex_unlock(&(config_locks()->relay_lock));
+ thread_mutex_unlock (&(config_locks()->relay_lock));
}
- INFO0 ("Slave thread shutting down");
+ INFO0 ("Slave thread shutdown complete");
+
return NULL;
}
<p><p>1.4 +14 -0 icecast/src/slave.h
Index: slave.h
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/slave.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- slave.h 2 Feb 2004 19:22:11 -0000 1.3
+++ slave.h 19 Feb 2004 20:28:21 -0000 1.4
@@ -13,8 +13,22 @@
#ifndef __SLAVE_H__
#define __SLAVE_H__
+typedef struct _relay_server {
+ char *server;
+ int port;
+ char *mount;
+ char *localmount;
+ struct source_tag *source;
+ int mp3metadata;
+ int running;
+ int cleanup;
+ struct _relay_server *next;
+} relay_server;
+
+
void slave_initialize(void);
void slave_shutdown(void);
void slave_recheck (void);
+relay_server *relay_free (relay_server *relay);
#endif /* __SLAVE_H__ */
<p><p>1.73 +24 -50 icecast/src/source.c
Index: source.c
===================================================================
RCS file: /usr/local/cvsroot/icecast/src/source.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -r1.72 -r1.73
--- source.c 19 Feb 2004 16:32:23 -0000 1.72
+++ source.c 19 Feb 2004 20:28:21 -0000 1.73
@@ -246,11 +246,13 @@
void source_clear_source (source_t *source)
{
#ifdef USE_YP
- int i;
+ int i;
#endif
DEBUG1 ("clearing source \"%s\"", source->mount);
client_destroy(source->client);
source->client = NULL;
+ source->parser = NULL;
+ source->con = NULL;
/* lets kick off any clients that are left on here */
avl_tree_rlock (source->client_tree);
@@ -281,15 +283,15 @@
source->ypdata[i] = NULL;
}
source->num_yp_directories = 0;
+
+ util_dict_free (source->audio_info);
+ source->audio_info = NULL;
#endif
source->listeners = 0;
source->no_mount = 0;
source->max_listeners = -1;
source->yp_public = 0;
- util_dict_free(source->audio_info);
- source->audio_info = NULL;
-
free(source->fallback_mount);
source->fallback_mount = NULL;
@@ -298,33 +300,26 @@
}
+/* Remove the provided source from the global tree and free it */
int source_free_source(void *key)
{
source_t *source = key;
-#ifdef USE_YP
- int i;
-#endif
- free(source->mount);
- free(source->fallback_mount);
- free(source->dumpfilename);
- client_destroy(source->client);
+ DEBUG1 ("freeing source \"%s\"", source->mount);
+ avl_tree_wlock (global.source_tree);
+ avl_delete (global.source_tree, source, NULL);
+ avl_tree_unlock (global.source_tree);
+
avl_tree_free(source->pending_tree, _free_client);
avl_tree_free(source->client_tree, _free_client);
- source->format->free_plugin(source->format);
-#ifdef USE_YP
- for (i=0; i<source->num_yp_directories; i++)
- {
- yp_destroy_ypdata(source->ypdata[i]);
- source->ypdata[i] = NULL;
- }
-#endif
- util_dict_free(source->audio_info);
- free(source);
+
+ free (source->mount);
+ free (source);
return 1;
}
+
client_t *source_find_client(source_t *source, int id)
{
client_t fakeclient;
@@ -455,27 +450,6 @@
/* grab a read lock, to make sure we get a chance to cleanup */
thread_rwlock_rlock(source->shutdown_rwlock);
- avl_tree_wlock(global.source_tree);
- /* Now, we must do a final check with write lock taken out that the
- * mountpoint is available..
- */
- if (source_find_mount_raw(source->mount) != NULL) {
- avl_tree_unlock(global.source_tree);
- if(source->send_return) {
- client_send_404(source->client, "Mountpoint in use");
- }
- global_lock();
- global.sources--;
- global_unlock();
- thread_rwlock_unlock(source->shutdown_rwlock);
- thread_exit(0);
- return NULL;
- }
- /* insert source onto source tree */
- avl_insert(global.source_tree, (void *)source);
- /* release write lock on global source tree */
- avl_tree_unlock(global.source_tree);
-
/* If we connected successfully, we can send the message (if requested)
* back
*/
@@ -491,6 +465,7 @@
stats_event(source->mount, "listeners", "0");
stats_event(source->mount, "type", source->format->format_description);
#ifdef USE_YP
+ source->audio_info = util_dict_new();
/* ice-* is icecast, icy-* is shoutcast */
if ((s = httpp_getvar(source->parser, "ice-url"))) {
add_yp_info(source, "server_url", s, YP_SERVER_URL);
@@ -847,6 +822,7 @@
done:
+ source->running = 0;
INFO1("Source \"%s\" exiting", source->mount);
#ifdef USE_YP
@@ -855,13 +831,11 @@
}
#endif
- /* Now, we must remove this source from the source tree before
- * removing the clients, otherwise new clients can sneak into the pending
- * tree after we've cleared it
+ /* we have de-activated the source now, so no more clients will be
+ * added, now move the listeners we have to the fallback (if any)
*/
- avl_tree_wlock(global.source_tree);
+ avl_tree_rlock(global.source_tree);
fallback_source = source_find_mount (source->fallback_mount);
- avl_delete (global.source_tree, source, NULL);
if (fallback_source != NULL)
source_move_clients (source, fallback_source);
@@ -882,10 +856,10 @@
/* release our hold on the lock so the main thread can continue cleaning up */
thread_rwlock_unlock(source->shutdown_rwlock);
- source_free_source(source);
+ /* we don't remove the source from the tree here, it may be a relay and
+ therefore reserved */
+ source_clear_source (source);
- thread_exit(0);
-
return NULL;
}
<p><p>--- >8 ----
List archives: http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body. No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.
More information about the commits
mailing list