mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
Bug 6195 - Deadlock solution by Matti
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@12136 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <linux/telephony.h>
|
#include <linux/telephony.h>
|
||||||
/* Still use some IXJ specific stuff */
|
/* Still use some IXJ specific stuff */
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
@@ -108,6 +109,9 @@ AST_MUTEX_DEFINE_STATIC(iflock);
|
|||||||
when it's doing something critical. */
|
when it's doing something critical. */
|
||||||
AST_MUTEX_DEFINE_STATIC(monlock);
|
AST_MUTEX_DEFINE_STATIC(monlock);
|
||||||
|
|
||||||
|
/* Boolean value whether the monitoring thread shall continue. */
|
||||||
|
static unsigned int monitor;
|
||||||
|
|
||||||
/* This is the thread for the monitor which checks for input on the channels
|
/* This is the thread for the monitor which checks for input on the channels
|
||||||
which are not currently in use. */
|
which are not currently in use. */
|
||||||
static pthread_t monitor_thread = AST_PTHREADT_NULL;
|
static pthread_t monitor_thread = AST_PTHREADT_NULL;
|
||||||
@@ -990,22 +994,12 @@ static void *do_monitor(void *data)
|
|||||||
int dotone;
|
int dotone;
|
||||||
/* This thread monitors all the frame relay interfaces which are not yet in use
|
/* This thread monitors all the frame relay interfaces which are not yet in use
|
||||||
(and thus do not have a separate thread) indefinitely */
|
(and thus do not have a separate thread) indefinitely */
|
||||||
/* From here on out, we die whenever asked */
|
while (monitor) {
|
||||||
if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL)) {
|
|
||||||
ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
for(;;) {
|
|
||||||
/* Don't let anybody kill us right away. Nobody should lock the interface list
|
/* Don't let anybody kill us right away. Nobody should lock the interface list
|
||||||
and wait for the monitor list, but the other way around is okay. */
|
and wait for the monitor list, but the other way around is okay. */
|
||||||
if (ast_mutex_lock(&monlock)) {
|
|
||||||
ast_log(LOG_ERROR, "Unable to grab monitor lock\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/* Lock the interface list */
|
/* Lock the interface list */
|
||||||
if (ast_mutex_lock(&iflock)) {
|
if (ast_mutex_lock(&iflock)) {
|
||||||
ast_log(LOG_ERROR, "Unable to grab interface lock\n");
|
ast_log(LOG_ERROR, "Unable to grab interface lock\n");
|
||||||
ast_mutex_unlock(&monlock);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
/* Build the stuff we're going to select on, that is the socket of every
|
/* Build the stuff we're going to select on, that is the socket of every
|
||||||
@@ -1015,7 +1009,7 @@ static void *do_monitor(void *data)
|
|||||||
FD_ZERO(&efds);
|
FD_ZERO(&efds);
|
||||||
i = iflist;
|
i = iflist;
|
||||||
dotone = 0;
|
dotone = 0;
|
||||||
while(i) {
|
while (i) {
|
||||||
if (FD_ISSET(i->fd, &rfds))
|
if (FD_ISSET(i->fd, &rfds))
|
||||||
ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
|
ast_log(LOG_WARNING, "Descriptor %d appears twice (%s)?\n", i->fd, i->dev);
|
||||||
if (!i->owner) {
|
if (!i->owner) {
|
||||||
@@ -1041,9 +1035,6 @@ static void *do_monitor(void *data)
|
|||||||
/* Okay, now that we know what to do, release the interface lock */
|
/* Okay, now that we know what to do, release the interface lock */
|
||||||
ast_mutex_unlock(&iflock);
|
ast_mutex_unlock(&iflock);
|
||||||
|
|
||||||
/* And from now on, we're okay to be killed, so release the monitor lock as well */
|
|
||||||
ast_mutex_unlock(&monlock);
|
|
||||||
|
|
||||||
/* Wait indefinitely for something to happen */
|
/* Wait indefinitely for something to happen */
|
||||||
if (dotone) {
|
if (dotone) {
|
||||||
/* If we're ready to recycle the time, set it to 30 ms */
|
/* If we're ready to recycle the time, set it to 30 ms */
|
||||||
@@ -1061,7 +1052,7 @@ static void *do_monitor(void *data)
|
|||||||
}
|
}
|
||||||
/* Okay, select has finished. Let's see what happened. */
|
/* Okay, select has finished. Let's see what happened. */
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
ast_log(LOG_WARNING, "select return %d: %s\n", res, strerror(errno));
|
ast_log(LOG_DEBUG, "select return %d: %s\n", res, strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* If there are no fd's changed, just continue, it's probably time
|
/* If there are no fd's changed, just continue, it's probably time
|
||||||
@@ -1092,7 +1083,6 @@ static void *do_monitor(void *data)
|
|||||||
}
|
}
|
||||||
ast_mutex_unlock(&iflock);
|
ast_mutex_unlock(&iflock);
|
||||||
}
|
}
|
||||||
/* Never reached */
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1113,16 +1103,17 @@ static int restart_monitor()
|
|||||||
}
|
}
|
||||||
if (monitor_thread != AST_PTHREADT_NULL) {
|
if (monitor_thread != AST_PTHREADT_NULL) {
|
||||||
if (ast_mutex_lock(&iflock)) {
|
if (ast_mutex_lock(&iflock)) {
|
||||||
ast_mutex_unlock(&monlock);
|
ast_mutex_unlock(&monlock);
|
||||||
ast_log(LOG_WARNING, "Unable to lock the interface list\n");
|
ast_log(LOG_WARNING, "Unable to lock the interface list\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pthread_cancel(monitor_thread);
|
monitor = 0;
|
||||||
#if 0
|
while (pthread_kill(monitor_thread, SIGURG) == 0)
|
||||||
|
sched_yield();
|
||||||
pthread_join(monitor_thread, NULL);
|
pthread_join(monitor_thread, NULL);
|
||||||
#endif
|
|
||||||
ast_mutex_unlock(&iflock);
|
ast_mutex_unlock(&iflock);
|
||||||
}
|
}
|
||||||
|
monitor = 1;
|
||||||
/* Start a new monitor */
|
/* Start a new monitor */
|
||||||
if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
|
||||||
ast_mutex_unlock(&monlock);
|
ast_mutex_unlock(&monlock);
|
||||||
@@ -1278,7 +1269,9 @@ static int __unload_module(void)
|
|||||||
}
|
}
|
||||||
if (!ast_mutex_lock(&monlock)) {
|
if (!ast_mutex_lock(&monlock)) {
|
||||||
if (monitor_thread > AST_PTHREADT_NULL) {
|
if (monitor_thread > AST_PTHREADT_NULL) {
|
||||||
pthread_cancel(monitor_thread);
|
monitor = 0;
|
||||||
|
while (pthread_kill(monitor_thread, SIGURG) == 0)
|
||||||
|
sched_yield();
|
||||||
pthread_join(monitor_thread, NULL);
|
pthread_join(monitor_thread, NULL);
|
||||||
}
|
}
|
||||||
monitor_thread = AST_PTHREADT_STOP;
|
monitor_thread = AST_PTHREADT_STOP;
|
||||||
|
Reference in New Issue
Block a user