diff options
author | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-07-05 19:48:42 +0000 |
---|---|---|
committer | tilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b> | 2010-07-05 19:48:42 +0000 |
commit | 4ad4864fca0fb13d27b20e3b35d26196c1a69e1d (patch) | |
tree | 55d3007a9a266a9246b5ca8b023229060e0086fe | |
parent | 60f0127018942259ac708815659636a000247b3d (diff) |
Command 'stop gracefully' doesn't.
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@273981 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | channels/chan_iax2.c | 32 | ||||
-rw-r--r-- | channels/chan_oss.c | 28 |
2 files changed, 44 insertions, 16 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 70adaa480..0fc3f70e9 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -172,6 +172,7 @@ static int timingfd = -1; /* Timing file descriptor */ static struct ast_netsock_list *netsock; static struct ast_netsock_list *outsock; /*!< used if sourceaddress specified and bindaddr == INADDR_ANY */ static int defaultsockfd = -1; +static int unloading; int (*iax2_regfunk)(const char *username, int onoff) = NULL; @@ -2324,6 +2325,12 @@ static void sched_delay_remove(struct sockaddr_in *sin, struct callno_entry *cal }; if ((peercnt = ao2_find(peercnts, &tmp, OBJ_POINTER))) { + if (unloading) { + peercnt_remove_cb(peercnt); + replace_callno(callno_entry); + return; + } + /* refcount is incremented with ao2_find. keep that ref for the scheduler */ if (option_debug) { ast_log(LOG_DEBUG, "schedule decrement of callno used for %s in %d seconds\n", ast_inet_ntoa(sin->sin_addr), MIN_REUSE_TIME); @@ -9976,12 +9983,14 @@ static void *iax2_process_thread(void *data) ast_atomic_fetchadd_int(&iaxactivethreadcount,1); pthread_cleanup_push(iax2_process_thread_cleanup, data); for(;;) { + pthread_testcancel(); + /* Wait for something to signal us to be awake */ ast_mutex_lock(&thread->lock); /* Flag that we're ready to accept signals */ thread->ready_for_signal = 1; - + /* Put into idle list if applicable */ if (put_into_idle) insert_idle_thread(thread); @@ -12491,8 +12500,10 @@ static int __unload_module(void) struct iax2_thread *thread = NULL; int x; + unloading = 1; + /* Make sure threads do not hold shared resources when they are canceled */ - + /* Grab the sched lock resource to keep it away from threads about to die */ /* Cancel the network thread, close the net socket */ if (netthreadid != AST_PTHREADT_NULL) { @@ -12505,13 +12516,13 @@ static int __unload_module(void) pthread_join(netthreadid, NULL); } if (schedthreadid != AST_PTHREADT_NULL) { - ast_mutex_lock(&sched_lock); + ast_mutex_lock(&sched_lock); pthread_cancel(schedthreadid); ast_cond_signal(&sched_cond); - ast_mutex_unlock(&sched_lock); + ast_mutex_unlock(&sched_lock); pthread_join(schedthreadid, NULL); } - + /* Call for all threads to halt */ AST_LIST_LOCK(&idle_list); AST_LIST_TRAVERSE_SAFE_BEGIN(&idle_list, thread, list) { @@ -12530,19 +12541,20 @@ static int __unload_module(void) AST_LIST_UNLOCK(&active_list); AST_LIST_LOCK(&dynamic_list); - AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) { + AST_LIST_TRAVERSE_SAFE_BEGIN(&dynamic_list, thread, list) { AST_LIST_REMOVE_CURRENT(&dynamic_list, list); pthread_cancel(thread->threadid); - } + } AST_LIST_TRAVERSE_SAFE_END - AST_LIST_UNLOCK(&dynamic_list); + AST_LIST_UNLOCK(&dynamic_list); AST_LIST_HEAD_DESTROY(&iaxq.queue); /* Wait for threads to exit */ - while(0 < iaxactivethreadcount) + while (0 < iaxactivethreadcount) { usleep(10000); - + } + ast_netsock_release(netsock); ast_netsock_release(outsock); for (x = 0; x < ARRAY_LEN(iaxs); x++) { diff --git a/channels/chan_oss.c b/channels/chan_oss.c index 27f4eea12..8f55daa55 100644 --- a/channels/chan_oss.c +++ b/channels/chan_oss.c @@ -50,6 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include <sys/time.h> #include <stdlib.h> #include <errno.h> +#include <signal.h> /* for pthread_kill(3) */ #ifdef __linux #include <linux/soundcard.h> @@ -606,6 +607,8 @@ static void *sound_thread(void *arg) fd_set rfds, wfds; int maxfd, res; + pthread_testcancel(); + FD_ZERO(&rfds); FD_ZERO(&wfds); FD_SET(o->sndcmd[0], &rfds); @@ -626,6 +629,7 @@ static void *sound_thread(void *arg) } /* ast_select emulates linux behaviour in terms of timeout handling */ res = ast_select(maxfd + 1, &rfds, &wfds, NULL, NULL); + pthread_testcancel(); if (res < 1) { ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); sleep(1); @@ -636,6 +640,7 @@ static void *sound_thread(void *arg) int i, what = -1; if (read(o->sndcmd[0], &what, sizeof(what)) != sizeof(what)) { + pthread_testcancel(); ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); continue; } @@ -1880,17 +1885,28 @@ static int unload_module(void) ast_cli_unregister_multiple(cli_oss, sizeof(cli_oss) / sizeof(struct ast_cli_entry)); for (o = oss_default.next; o; o = o->next) { + if (o->owner) { + ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); + /* Give the channel a chance to go away */ + sched_yield(); + } + if (o->owner) { + return -1; + } + oss_default.next = o->next; + if (o->sthread > 0) { + pthread_cancel(o->sthread); + pthread_kill(o->sthread, SIGURG); + pthread_join(o->sthread, NULL); + } close(o->sounddev); if (o->sndcmd[0] > 0) { close(o->sndcmd[0]); close(o->sndcmd[1]); } - if (o->owner) - ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD); - if (o->owner) - return -1; - /* XXX what about the thread ? */ - /* XXX what about the memory allocated ? */ + if (o->sthread > 0) { + free(o); + } } return 0; } |