aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-05 19:48:42 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2010-07-05 19:48:42 +0000
commit4ad4864fca0fb13d27b20e3b35d26196c1a69e1d (patch)
tree55d3007a9a266a9246b5ca8b023229060e0086fe /channels
parent60f0127018942259ac708815659636a000247b3d (diff)
Command 'stop gracefully' doesn't.
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.4@273981 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_iax2.c32
-rw-r--r--channels/chan_oss.c28
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;
}