1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-06-23 06:25:24 +00:00

bump to kh17. fix failing relay crash case. fix flashpolcy crash case.

fix memory corruption case when moving clients between workers.
some minor timing changes


svn path=/icecast/branches/kh/icecast/; revision=16632
This commit is contained in:
Karl Heyes 2009-10-11 01:20:04 +00:00
parent de49138869
commit 9a7a36acc4
12 changed files with 82 additions and 55 deletions

7
NEWS
View File

@ -16,6 +16,13 @@ Feature differences from SVN trunk
any extra tags are show in the conf/icecast.xml.dist file
2.3.2-kh17
. fix possible memory corruption when using multiple workers
. a few minor timing changes, nothing major.
. fix possible race case in multiple file handle close
. kh16b. fix possible crash case with relay failing
. kh16a. some fserve changes exposed a crash bug with flash clients.
2.3.2-kh16
. you can now fallback to file if the initial mountpont is not available as long
as there is a limit-rate set at some point within the fallback chain.

View File

@ -95,7 +95,7 @@
#define PACKAGE_NAME "Icecast"
/* Version number of package */
#define VERSION "2.3.2-kh16"
#define VERSION "2.3.2-kh17"
/* Define to the version of this package. */
#define PACKAGE_VERSION VERSION

View File

@ -1,4 +1,4 @@
AC_INIT([Icecast], [2.3.2-kh16], [karl@xiph.org])
AC_INIT([Icecast], [2.3.2-kh17], [karl@xiph.org])
AC_PREREQ(2.59)
AC_CONFIG_SRCDIR(src/main.c)

View File

@ -317,29 +317,37 @@ worker_t *find_least_busy_handler (void)
}
void client_change_worker (client_t *client, worker_t *dest_worker)
static void worker_add_client (worker_t *worker, client_t *client)
{
*worker->last_p = client;
worker->last_p = &client->next_on_worker;
client->worker = worker;
++worker->count;
if (worker->wakeup_ms - worker->time_ms > 15)
thread_cond_signal (&worker->cond); /* wake thread if required */
}
int client_change_worker (client_t *client, worker_t *dest_worker)
{
worker_t *this_worker = client->worker;
if (dest_worker->running == 0)
return 0;
// make sure this client list is ok
*this_worker->current_p = client->next_on_worker;
if (client->next_on_worker == NULL)
this_worker->last_p = this_worker->current_p;
this_worker->count--;
thread_mutex_unlock (&this_worker->lock);
client->next_on_worker = NULL;
thread_mutex_lock (&dest_worker->lock);
if (dest_worker->running)
{
client->worker = dest_worker;
*dest_worker->last_p = client;
dest_worker->last_p = &client->next_on_worker;
dest_worker->count++;
client->flags |= CLIENT_HAS_CHANGED_THREAD;
// make client inactive so that the destination thread does not run it straight away
client->flags &= ~CLIENT_ACTIVE;
}
worker_add_client (dest_worker, client);
thread_mutex_unlock (&dest_worker->lock);
thread_mutex_lock (&this_worker->lock);
return 1;
}
@ -354,12 +362,7 @@ void client_add_worker (client_t *client)
thread_rwlock_unlock (&workers_lock);
client->schedule_ms = handler->time_ms;
*handler->last_p = client;
handler->last_p = &client->next_on_worker;
client->worker = handler;
++handler->count;
if (handler->wakeup_ms - handler->time_ms > 15)
thread_cond_signal (&handler->cond); /* wake thread if required */
worker_add_client (handler, client);
thread_mutex_unlock (&handler->lock);
}
@ -406,13 +409,9 @@ void *worker (void *arg)
ret = client->ops->process (client);
/* special handler, client has moved away to another worker */
if (client->flags & CLIENT_HAS_CHANGED_THREAD)
if (ret > 0)
{
client->flags &= ~CLIENT_HAS_CHANGED_THREAD;
client->flags |= CLIENT_ACTIVE;
client = *prevp;
if (client == NULL)
handler->last_p = prevp;
continue;
}
if (ret < 0)

View File

@ -131,7 +131,7 @@ int client_send_bytes (client_t *client, const void *buf, unsigned len);
int client_read_bytes (client_t *client, void *buf, unsigned len);
void client_set_queue (client_t *client, refbuf_t *refbuf);
void client_change_worker (client_t *client, worker_t *dest_worker);
int client_change_worker (client_t *client, worker_t *dest_worker);
void client_add_worker (client_t *client);
worker_t *find_least_busy_handler (void);
void workers_adjust (int new_count);
@ -141,7 +141,7 @@ void workers_adjust (int new_count);
#define CLIENT_ACTIVE (001)
#define CLIENT_AUTHENTICATED (002)
#define CLIENT_IS_SLAVE (004)
#define CLIENT_HAS_CHANGED_THREAD (010)
#define CLIENT_NO_CONTENT_LENGTH (020)
#define CLIENT_HAS_INTRO_CONTENT (040)
#define CLIENT_FORMAT_BIT (01000)

View File

@ -704,6 +704,7 @@ static int http_client_request (client_t *client)
fb.flags = FS_NORMAL|FS_USE_ADMIN;
fb.fallback = NULL;
fb.limit = 0;
client->respcode = 200;
refbuf_release (refbuf);
client->shared_data = NULL;
client->check_buffer = format_generic_write_to_client;

View File

@ -66,11 +66,20 @@ void format_plugin_clear (format_plugin_t *format)
if (format == NULL)
return;
rate_free (format->in_bitrate);
format->in_bitrate = NULL;
rate_free (format->out_bitrate);
format->out_bitrate = NULL;
free (format->charset);
format->charset = NULL;
if (format->free_plugin)
format->free_plugin (format);
format->get_buffer = NULL;
format->write_buf_to_client = NULL;
format->write_buf_to_file = NULL;
format->create_client_data = NULL;
format->free_plugin = NULL;
format->set_tag = NULL;
format->apply_settings = NULL;
}

View File

@ -188,6 +188,7 @@ static int _compare_fh(void *arg, void *a, void *b)
static int _delete_fh (void *mapping)
{
fh_node *fh = mapping;
fh->refcount--;
if (fh->refcount)
WARN2 ("handle for %s has refcount %d", fh->finfo.mount, fh->refcount);
else
@ -242,6 +243,7 @@ static fh_node *open_fh (fbinfo *finfo, client_t *client)
{
free (fh);
thread_mutex_lock (&result->lock);
avl_tree_unlock (fh_cache);
result->refcount++;
if (client)
{
@ -259,7 +261,6 @@ static fh_node *open_fh (fbinfo *finfo, client_t *client)
}
}
DEBUG2 ("refcount now %d for %s", result->refcount, result->finfo.mount);
avl_tree_unlock (fh_cache);
return result;
}
@ -578,11 +579,11 @@ int fserve_client_create (client_t *httpclient, const char *path)
// fh must be locked before calling this
static void fh_release (fh_node *fh)
{
fh->refcount--;
if (fh->finfo.mount[0])
DEBUG2 ("refcount now %d on %s", fh->refcount, fh->finfo.mount);
if (fh->refcount)
if (fh->refcount > 1)
{
fh->refcount--;
thread_mutex_unlock (&fh->lock);
return;
}
@ -592,7 +593,7 @@ static void fh_release (fh_node *fh)
thread_mutex_unlock (&fh->lock);
avl_tree_wlock (fh_cache);
thread_mutex_lock (&fh->lock);
if (fh->refcount)
if (fh->refcount > 1)
thread_mutex_unlock (&fh->lock);
else
avl_delete (fh_cache, fh, _delete_fh);
@ -732,7 +733,7 @@ static int prefile_send (client_t *client)
if (written > 30000)
break;
}
client->schedule_ms = client->worker->time_ms + 150;
client->schedule_ms = client->worker->time_ms + 100;
return 0;
}

View File

@ -1259,8 +1259,7 @@ static int relay_read (client_t *client)
source->flags &= ~SOURCE_RUNNING;
if (relay->on_demand && source->listeners == 0)
source->flags &= ~SOURCE_RUNNING;
source_read (source);
return 0;
return source_read (source);
}
if (relay->running && relay->enable)
{

View File

@ -72,8 +72,8 @@ static int send_to_listener (client_t *client);
static int http_source_listener (client_t *client);
static int http_source_intro (client_t *client);
static int locate_start_on_queue (source_t *source, client_t *client);
static void listener_change_worker (client_t *client, source_t *source);
static void source_change_worker (source_t *source);
static int listener_change_worker (client_t *client, source_t *source);
static int source_change_worker (source_t *source);
static int source_client_callback (client_t *client);
#ifdef _WIN32
@ -412,7 +412,7 @@ static void update_source_stats (source_t *source)
* and sent back, however NULL is also valid as in the case of a short
* timeout and there's no data pending.
*/
void source_read (source_t *source)
int source_read (source_t *source)
{
client_t *client = source->client;
refbuf_t *refbuf = NULL;
@ -445,11 +445,10 @@ void source_read (source_t *source)
}
if (current >= source->client_stats_update)
{
source_change_worker (source);
update_source_stats (source);
source->client_stats_update = current + source->stats_interval;
thread_mutex_unlock (&source->lock);
return;
if (source_change_worker (source))
return 1;
}
if (source->limit_rate)
{
@ -486,6 +485,8 @@ void source_read (source_t *source)
source->skip_duration = 30;
else
source->skip_duration = (long)(source->skip_duration * 1.8);
if (source->skip_duration > 700)
source->skip_duration = 700;
break;
}
source->skip_duration = (long)(source->skip_duration * 0.9);
@ -570,6 +571,7 @@ void source_read (source_t *source)
if (skip)
client->schedule_ms = client->worker->time_ms + source->skip_duration;
thread_mutex_unlock (&source->lock);
return 0;
}
@ -585,7 +587,7 @@ static int source_client_read (client_t *client)
INFO1 ("streaming duration expired on %s", source->mount);
}
if (source_running (source))
source_read (source);
return source_read (source);
else
{
if ((source->flags & SOURCE_TERMINATING) == 0)
@ -845,7 +847,8 @@ static int send_to_listener (client_t *client)
// do we migrate this listener to the same handler as the source client
if (source->client && source->client->worker != client->worker)
listener_change_worker (client, source);
if (listener_change_worker (client, source))
return 1;
client->schedule_ms = client->worker->time_ms;
while (loop)
@ -867,12 +870,12 @@ static int send_to_listener (client_t *client)
if (bytes < 0)
break; /* can't write any more */
client->schedule_ms += 100;
client->schedule_ms += 40;
total_written += bytes;
loop--;
}
if (loop == 0)
client->schedule_ms -= 500;
client->schedule_ms -= 190;
rate_add (source->format->out_bitrate, total_written, client->worker->time_ms);
global_add_bitrates (global.out_bitrate, total_written, client->worker->time_ms);
source->bytes_sent_since_update += total_written;
@ -1852,10 +1855,11 @@ int source_startup (client_t *client, const char *uri)
/* check to see if the source client can be moved to a less busy worker thread.
* we only move the source client, not the listeners, they will move later
*/
void source_change_worker (source_t *source)
int source_change_worker (source_t *source)
{
client_t *client = source->client;
worker_t *this_worker = client->worker, *worker;
int ret = 0;
thread_rwlock_rlock (&workers_lock);
worker = find_least_busy_handler ();
@ -1864,22 +1868,26 @@ void source_change_worker (source_t *source)
if (worker->count + source->listeners + 10 < client->worker->count)
{
thread_mutex_unlock (&source->lock);
client_change_worker (client, worker);
DEBUG2 ("moving source from %p to %p", this_worker, worker);
thread_mutex_lock (&source->lock);
ret = client_change_worker (client, worker);
if (ret)
DEBUG2 ("moving source from %p to %p", this_worker, worker);
else
thread_mutex_lock (&source->lock);
}
}
thread_rwlock_unlock (&workers_lock);
return ret;
}
/* move listener client to worker theread that the source is on. This will
* help cache but prevent overloading a single worker with many listeners.
*/
void listener_change_worker (client_t *client, source_t *source)
int listener_change_worker (client_t *client, source_t *source)
{
worker_t *this_worker = client->worker, *dest_worker;
long diff;
int ret = 0;
thread_rwlock_rlock (&workers_lock);
dest_worker = source->client->worker;
@ -1888,10 +1896,13 @@ void listener_change_worker (client_t *client, source_t *source)
if (diff < 1000 && this_worker != dest_worker)
{
thread_mutex_unlock (&source->lock);
client_change_worker (client, dest_worker);
DEBUG2 ("moving listener from %p to %p", this_worker, dest_worker);
thread_mutex_lock (&source->lock);
ret = client_change_worker (client, dest_worker);
if (ret)
DEBUG2 ("moving listener from %p to %p", this_worker, dest_worker);
else
thread_mutex_lock (&source->lock);
}
thread_rwlock_unlock (&workers_lock);
return ret;
}

View File

@ -106,7 +106,7 @@ void source_listener_detach (client_t *client);
void source_main(source_t *source);
void source_recheck_mounts (int update_all);
int source_add_listener (const char *mount, mount_proxy *mountinfo, client_t *client);
void source_read (source_t *source);
int source_read (source_t *source);
void source_setup_listener (source_t *source, client_t *client);
void source_init (source_t *source);
void source_shutdown (source_t *source, int with_fallback);

View File

@ -3,7 +3,7 @@
[Setup]
AppName=Icecast2-KH
AppVerName=Icecast v2.3.2-kh16
AppVerName=Icecast v2.3.2-kh17
AppPublisherURL=http://www.icecast.org
AppSupportURL=http://www.icecast.org
AppUpdatesURL=http://www.icecast.org
@ -13,10 +13,10 @@ AllowNoIcons=yes
LicenseFile=..\COPYING
InfoAfterFile=..\README
OutputDir=.
OutputBaseFilename=icecast2_win32_v2.3.2-kh16_setup
OutputBaseFilename=icecast2_win32_v2.3.2-kh17_setup
WizardImageFile=icecast2logo2.bmp
WizardImageStretch=no
VersionInfoProductVersion=kh16
VersionInfoProductVersion=kh17
VersionInfoVersion=2.3.2
; uncomment the following line if you want your installation to run on NT 3.51 too.
; MinVersion=4,3.51