Fixed major memory leak in threads.
Added automatic restart when no module is busy. git-svn-id: http://voip.null.ro/svn/yate@101 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
6d49aa01b6
commit
92064e1651
14
Makefile.in
14
Makefile.in
|
@ -13,7 +13,7 @@ DEFS :=
|
||||||
LIBAUX:= -ldl
|
LIBAUX:= -ldl
|
||||||
LIBTHR:= -lpthread
|
LIBTHR:= -lpthread
|
||||||
INCLUDES := -I@srcdir@
|
INCLUDES := -I@srcdir@
|
||||||
CFLAGS := -O2 @MODULE_CFLAGS@ -finline -Winline
|
CFLAGS := -O2 @MODULE_CFLAGS@ @INLINE_FLAGS@
|
||||||
LDFLAGS:=
|
LDFLAGS:=
|
||||||
|
|
||||||
PROGS:= yate
|
PROGS:= yate
|
||||||
|
@ -84,18 +84,6 @@ love:
|
||||||
war:
|
war:
|
||||||
@echo 'Please make love instead!'
|
@echo 'Please make love instead!'
|
||||||
|
|
||||||
.PHONY: run
|
|
||||||
run: all
|
|
||||||
-./run
|
|
||||||
|
|
||||||
.PHONY: gdb-run
|
|
||||||
gdb-run: all
|
|
||||||
-./run --gdb
|
|
||||||
|
|
||||||
.PHONY: gdb-core
|
|
||||||
gdb-core: all
|
|
||||||
-./run --core
|
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: engine
|
test: engine
|
||||||
$(MAKE) -C ./test all
|
$(MAKE) -C ./test all
|
||||||
|
|
|
@ -569,6 +569,8 @@ public:
|
||||||
GtkClientPlugin();
|
GtkClientPlugin();
|
||||||
~GtkClientPlugin();
|
~GtkClientPlugin();
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
virtual bool isBusy() const
|
||||||
|
{ return true; }
|
||||||
private:
|
private:
|
||||||
MessageHandler *m_route;
|
MessageHandler *m_route;
|
||||||
bool m_init;
|
bool m_init;
|
||||||
|
@ -602,7 +604,8 @@ void GtkClientPlugin::initialize()
|
||||||
{
|
{
|
||||||
m_route = new GtkClientHandler(priority);
|
m_route = new GtkClientHandler(priority);
|
||||||
Engine::install(m_route);
|
Engine::install(m_route);
|
||||||
new GtkClient;
|
GtkClient *gtk = new GtkClient;
|
||||||
|
gtk->startup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// int argc = 0;
|
// int argc = 0;
|
||||||
|
|
20
configure.in
20
configure.in
|
@ -41,6 +41,26 @@ AC_CACHE_SAVE
|
||||||
AC_CHECK_LIB([dl], [dlopen], , [AC_MSG_ERROR([This library is required.])])
|
AC_CHECK_LIB([dl], [dlopen], , [AC_MSG_ERROR([This library is required.])])
|
||||||
AC_CHECK_LIB([pthread], [pthread_create], , [AC_MSG_ERROR([This library is required.])])
|
AC_CHECK_LIB([pthread], [pthread_create], , [AC_MSG_ERROR([This library is required.])])
|
||||||
|
|
||||||
|
# Check for compile options
|
||||||
|
INLINE_FLAGS=""
|
||||||
|
AC_ARG_ENABLE(inline,AC_HELP_STRING([--enable-inline],[Enable inlining of functions]),want_inline=$enableval,want_inline=auto)
|
||||||
|
AC_MSG_CHECKING([whether to use inline functions])
|
||||||
|
case "x$want_inline" in
|
||||||
|
xyes)
|
||||||
|
INLINE_FLAGS="-finline -Winline"
|
||||||
|
;;
|
||||||
|
xno)
|
||||||
|
INLINE_FLAGS="-fno-inline"
|
||||||
|
;;
|
||||||
|
xauto)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
AC_ERROR([Invalid argument passed to --enable-inline])
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AC_MSG_RESULT([$want_inline])
|
||||||
|
AC_SUBST(INLINE_FLAGS)
|
||||||
|
|
||||||
# Checks for optional libraries.
|
# Checks for optional libraries.
|
||||||
|
|
||||||
HAVE_PGSQL=no
|
HAVE_PGSQL=no
|
||||||
|
|
|
@ -427,10 +427,13 @@ ThreadedSource::~ThreadedSource()
|
||||||
delete m_thread;
|
delete m_thread;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadedSource::start(const char *name)
|
bool ThreadedSource::start(const char *name)
|
||||||
{
|
{
|
||||||
if (!m_thread)
|
if (!m_thread) {
|
||||||
m_thread = new ThreadedSourcePrivate(this,name);
|
m_thread = new ThreadedSourcePrivate(this,name);
|
||||||
|
m_thread->startup();
|
||||||
|
}
|
||||||
|
return m_thread->running();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadedSource::cleanup()
|
void ThreadedSource::cleanup()
|
||||||
|
|
|
@ -52,6 +52,7 @@ using namespace TelEngine;
|
||||||
#define MAX_SANITY 5
|
#define MAX_SANITY 5
|
||||||
|
|
||||||
static unsigned long long s_nextinit = 0;
|
static unsigned long long s_nextinit = 0;
|
||||||
|
static unsigned long long s_restarts = 0;
|
||||||
static bool s_makeworker = true;
|
static bool s_makeworker = true;
|
||||||
static bool s_keepclosing = false;
|
static bool s_keepclosing = false;
|
||||||
static int s_super_handle = -1;
|
static int s_super_handle = -1;
|
||||||
|
@ -158,6 +159,7 @@ bool EngineStatusHandler::received(Message &msg)
|
||||||
return false;
|
return false;
|
||||||
msg.retValue() << "engine";
|
msg.retValue() << "engine";
|
||||||
msg.retValue() << ",plugins=" << plugins.count();
|
msg.retValue() << ",plugins=" << plugins.count();
|
||||||
|
msg.retValue() << ",inuse=" << Engine::self()->usedPlugins();
|
||||||
msg.retValue() << ",threads=" << Thread::count();
|
msg.retValue() << ",threads=" << Thread::count();
|
||||||
msg.retValue() << ",workers=" << EnginePrivate::count;
|
msg.retValue() << ",workers=" << EnginePrivate::count;
|
||||||
msg.retValue() << ",mutexes=" << Mutex::count();
|
msg.retValue() << ",mutexes=" << Mutex::count();
|
||||||
|
@ -198,10 +200,17 @@ int Engine::run()
|
||||||
{
|
{
|
||||||
Debug(DebugAll,"Engine::run()");
|
Debug(DebugAll,"Engine::run()");
|
||||||
install(new EngineStatusHandler);
|
install(new EngineStatusHandler);
|
||||||
if (s_super_handle >= 0)
|
|
||||||
install(new EngineSuperHandler);
|
|
||||||
loadPlugins();
|
loadPlugins();
|
||||||
Debug(DebugInfo,"plugins.count() = %d",plugins.count());
|
Debug(DebugInfo,"plugins.count() = %d",plugins.count());
|
||||||
|
if (s_super_handle >= 0) {
|
||||||
|
install(new EngineSuperHandler);
|
||||||
|
if (s_restarts)
|
||||||
|
s_restarts = 1000000 * s_restarts + Time::now();
|
||||||
|
}
|
||||||
|
else if (s_restarts) {
|
||||||
|
Debug(DebugWarn,"No supervisor - disabling automatic restarts");
|
||||||
|
s_restarts = 0;
|
||||||
|
}
|
||||||
initPlugins();
|
initPlugins();
|
||||||
::signal(SIGINT,sighandler);
|
::signal(SIGINT,sighandler);
|
||||||
::signal(SIGTERM,sighandler);
|
::signal(SIGTERM,sighandler);
|
||||||
|
@ -219,11 +228,21 @@ int Engine::run()
|
||||||
// Create worker thread if we didn't hear about any of them in a while
|
// Create worker thread if we didn't hear about any of them in a while
|
||||||
if (s_makeworker && (EnginePrivate::count < s_maxworkers)) {
|
if (s_makeworker && (EnginePrivate::count < s_maxworkers)) {
|
||||||
Debug(DebugInfo,"Creating new message dispatching thread");
|
Debug(DebugInfo,"Creating new message dispatching thread");
|
||||||
new EnginePrivate;
|
EnginePrivate *prv = new EnginePrivate;
|
||||||
|
prv->startup();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
s_makeworker = true;
|
s_makeworker = true;
|
||||||
|
|
||||||
|
if (s_restarts && (Time::now() >= s_restarts)) {
|
||||||
|
if (!(usedPlugins() || dispatch("engine.busy"))) {
|
||||||
|
s_haltcode = 128;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// If we cannot restart now try again in 10s
|
||||||
|
s_restarts = Time::now() + 10000000;
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to sleep until the next full second
|
// Attempt to sleep until the next full second
|
||||||
unsigned long t = (Time::now() + corr) % 1000000;
|
unsigned long t = (Time::now() + corr) % 1000000;
|
||||||
::usleep(1000000 - t);
|
::usleep(1000000 - t);
|
||||||
|
@ -298,6 +317,8 @@ void Engine::loadPlugins()
|
||||||
const char *name = cfg.getValue("general","modpath");
|
const char *name = cfg.getValue("general","modpath");
|
||||||
if (name)
|
if (name)
|
||||||
s_modpath = name;
|
s_modpath = name;
|
||||||
|
s_maxworkers = cfg.getIntValue("general","maxworkers",s_maxworkers);
|
||||||
|
s_restarts = cfg.getIntValue("general","restarts");
|
||||||
NamedList *l = cfg.getSection("preload");
|
NamedList *l = cfg.getSection("preload");
|
||||||
if (l) {
|
if (l) {
|
||||||
unsigned int len = l->length();
|
unsigned int len = l->length();
|
||||||
|
@ -351,6 +372,18 @@ void Engine::initPlugins()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Engine::usedPlugins()
|
||||||
|
{
|
||||||
|
int used = 0;
|
||||||
|
ObjList *l = &plugins;
|
||||||
|
for (; l; l = l->next()) {
|
||||||
|
Plugin *p = static_cast<Plugin *>(l->get());
|
||||||
|
if (p && p->isBusy())
|
||||||
|
used++;
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
void Engine::halt(unsigned int code)
|
void Engine::halt(unsigned int code)
|
||||||
{
|
{
|
||||||
s_haltcode = code;
|
s_haltcode = code;
|
||||||
|
@ -453,8 +486,11 @@ static int supervise(void)
|
||||||
if (tmp > 0) {
|
if (tmp > 0) {
|
||||||
// Child exited for some reason
|
// Child exited for some reason
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
s_runagain = false;
|
|
||||||
retcode = WEXITSTATUS(status);
|
retcode = WEXITSTATUS(status);
|
||||||
|
if (retcode <= 127)
|
||||||
|
s_runagain = false;
|
||||||
|
else
|
||||||
|
retcode &= 127;
|
||||||
}
|
}
|
||||||
else if (WIFSIGNALED(status)) {
|
else if (WIFSIGNALED(status)) {
|
||||||
retcode = WTERMSIG(status);
|
retcode = WTERMSIG(status);
|
||||||
|
@ -484,7 +520,7 @@ static int supervise(void)
|
||||||
// If -Da was specified try to get a corefile
|
// If -Da was specified try to get a corefile
|
||||||
if (s_sigabrt) {
|
if (s_sigabrt) {
|
||||||
::kill(s_childpid,SIGABRT);
|
::kill(s_childpid,SIGABRT);
|
||||||
::usleep(10000);
|
::usleep(250000);
|
||||||
}
|
}
|
||||||
::kill(s_childpid,SIGKILL);
|
::kill(s_childpid,SIGKILL);
|
||||||
::usleep(10000);
|
::usleep(10000);
|
||||||
|
@ -616,7 +652,6 @@ int Engine::main(int argc, const char **argv, const char **environ)
|
||||||
while (*++pc) {
|
while (*++pc) {
|
||||||
switch (*pc) {
|
switch (*pc) {
|
||||||
case 'a':
|
case 'a':
|
||||||
abortOnBug(true);
|
|
||||||
s_sigabrt = true;
|
s_sigabrt = true;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
|
@ -681,6 +716,7 @@ int Engine::main(int argc, const char **argv, const char **environ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debugLevel(debug_level);
|
debugLevel(debug_level);
|
||||||
|
abortOnBug(s_sigabrt);
|
||||||
|
|
||||||
int retcode = supervised ? supervise() : -1;
|
int retcode = supervised ? supervise() : -1;
|
||||||
if (retcode >= 0)
|
if (retcode >= 0)
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
Thread *m_thread;
|
Thread *m_thread;
|
||||||
pthread_t thread;
|
pthread_t thread;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
|
bool m_started;
|
||||||
bool m_updest;
|
bool m_updest;
|
||||||
const char *m_name;
|
const char *m_name;
|
||||||
private:
|
private:
|
||||||
|
@ -66,7 +67,7 @@ ThreadPrivate *ThreadPrivate::create(Thread *t,const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadPrivate::ThreadPrivate(Thread *t,const char *name)
|
ThreadPrivate::ThreadPrivate(Thread *t,const char *name)
|
||||||
: m_thread(t), m_running(false), m_updest(true), m_name(name)
|
: m_thread(t), m_running(false), m_started(false), m_updest(true), m_name(name)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Debugger debug("ThreadPrivate::ThreadPrivate","(%p,\"%s\") [%p]",t,name,this);
|
Debugger debug("ThreadPrivate::ThreadPrivate","(%p,\"%s\") [%p]",t,name,this);
|
||||||
|
@ -121,8 +122,9 @@ void ThreadPrivate::run()
|
||||||
::pthread_setspecific(current_key,this);
|
::pthread_setspecific(current_key,this);
|
||||||
pthread_cleanup_push(cleanupFunc,this);
|
pthread_cleanup_push(cleanupFunc,this);
|
||||||
::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
|
::pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,0);
|
||||||
|
::pthread_detach(::pthread_self());
|
||||||
|
|
||||||
while (!m_running)
|
while (!m_started)
|
||||||
::usleep(10);
|
::usleep(10);
|
||||||
m_thread->run();
|
m_thread->run();
|
||||||
pthread_cleanup_pop(1);
|
pthread_cleanup_pop(1);
|
||||||
|
@ -289,7 +291,15 @@ bool Thread::error() const
|
||||||
|
|
||||||
bool Thread::running() const
|
bool Thread::running() const
|
||||||
{
|
{
|
||||||
return m_private ? m_private->m_running : false;
|
return m_private ? m_private->m_started : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Thread::startup()
|
||||||
|
{
|
||||||
|
if (!m_private)
|
||||||
|
return false;
|
||||||
|
m_private->m_started = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread *Thread::current()
|
Thread *Thread::current()
|
||||||
|
|
|
@ -11,7 +11,7 @@ CC := g++ -Wall
|
||||||
SED := sed
|
SED := sed
|
||||||
DEFS :=
|
DEFS :=
|
||||||
INCLUDES := -I@top_srcdir@
|
INCLUDES := -I@top_srcdir@
|
||||||
CFLAGS := -O2 @MODULE_CFLAGS@
|
CFLAGS := -O2 @MODULE_CFLAGS@ @INLINE_FLAGS@
|
||||||
LDFLAGS:= -L.. -lyate
|
LDFLAGS:= -L.. -lyate
|
||||||
MODFLAGS:= @MODULE_LDFLAGS@
|
MODFLAGS:= @MODULE_LDFLAGS@
|
||||||
MODSTRIP:= @MODULE_SYMBOLS@
|
MODSTRIP:= @MODULE_SYMBOLS@
|
||||||
|
|
|
@ -164,6 +164,7 @@ public:
|
||||||
ExtModulePlugin();
|
ExtModulePlugin();
|
||||||
~ExtModulePlugin();
|
~ExtModulePlugin();
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
virtual bool isBusy() const;
|
||||||
private:
|
private:
|
||||||
ExtModHandler *m_handler;
|
ExtModHandler *m_handler;
|
||||||
};
|
};
|
||||||
|
@ -360,7 +361,8 @@ ExtModReceiver::~ExtModReceiver()
|
||||||
bool ExtModReceiver::start()
|
bool ExtModReceiver::start()
|
||||||
{
|
{
|
||||||
if (m_pid < 0) {
|
if (m_pid < 0) {
|
||||||
new ExtThread(this);
|
ExtThread *ext = new ExtThread(this);
|
||||||
|
ext->startup();
|
||||||
while (m_pid < 0)
|
while (m_pid < 0)
|
||||||
Thread::yield();
|
Thread::yield();
|
||||||
}
|
}
|
||||||
|
@ -827,6 +829,11 @@ ExtModulePlugin::~ExtModulePlugin()
|
||||||
s_chans.clear();
|
s_chans.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ExtModulePlugin::isBusy() const
|
||||||
|
{
|
||||||
|
return (s_chans.count() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
void ExtModulePlugin::initialize()
|
void ExtModulePlugin::initialize()
|
||||||
{
|
{
|
||||||
Output("Initializing module ExtModule");
|
Output("Initializing module ExtModule");
|
||||||
|
|
|
@ -30,6 +30,7 @@ public:
|
||||||
GsmPlugin();
|
GsmPlugin();
|
||||||
~GsmPlugin();
|
~GsmPlugin();
|
||||||
virtual void initialize() { }
|
virtual void initialize() { }
|
||||||
|
virtual bool isBusy() const;
|
||||||
virtual DataTranslator *create(const String &sFormat, const String &dFormat);
|
virtual DataTranslator *create(const String &sFormat, const String &dFormat);
|
||||||
virtual const TranslatorCaps *getCapabilities() const;
|
virtual const TranslatorCaps *getCapabilities() const;
|
||||||
};
|
};
|
||||||
|
@ -119,6 +120,11 @@ GsmPlugin::~GsmPlugin()
|
||||||
Output("Unloading module GSM with %d codecs still in use",count);
|
Output("Unloading module GSM with %d codecs still in use",count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GsmPlugin::isBusy() const
|
||||||
|
{
|
||||||
|
return (count != 0);
|
||||||
|
}
|
||||||
|
|
||||||
DataTranslator *GsmPlugin::create(const String &sFormat, const String &dFormat)
|
DataTranslator *GsmPlugin::create(const String &sFormat, const String &dFormat)
|
||||||
{
|
{
|
||||||
if (sFormat == "slin" && dFormat == "gsm")
|
if (sFormat == "slin" && dFormat == "gsm")
|
||||||
|
|
|
@ -283,12 +283,10 @@ class H323MsgThread : public Thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
H323MsgThread(Message *msg, const char *id)
|
H323MsgThread(Message *msg, const char *id)
|
||||||
: Thread("H323MsgThread"), m_msg(msg), m_id(id) { m_mutex.lock(); }
|
: Thread("H323MsgThread"), m_msg(msg), m_id(id) { }
|
||||||
virtual void run();
|
virtual void run();
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
bool route();
|
bool route();
|
||||||
inline void resume()
|
|
||||||
{ m_mutex.unlock(); }
|
|
||||||
inline static int count()
|
inline static int count()
|
||||||
{ return s_count; }
|
{ return s_count; }
|
||||||
inline static int routed()
|
inline static int routed()
|
||||||
|
@ -296,7 +294,6 @@ public:
|
||||||
private:
|
private:
|
||||||
Message *m_msg;
|
Message *m_msg;
|
||||||
String m_id;
|
String m_id;
|
||||||
Mutex m_mutex;
|
|
||||||
static int s_count;
|
static int s_count;
|
||||||
static int s_routed;
|
static int s_routed;
|
||||||
};
|
};
|
||||||
|
@ -314,6 +311,7 @@ public:
|
||||||
H323Plugin();
|
H323Plugin();
|
||||||
virtual ~H323Plugin();
|
virtual ~H323Plugin();
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
virtual bool isBusy() const;
|
||||||
void cleanup();
|
void cleanup();
|
||||||
YateH323Connection *findConnectionLock(const char *id);
|
YateH323Connection *findConnectionLock(const char *id);
|
||||||
inline YateH323EndPoint *ep()
|
inline YateH323EndPoint *ep()
|
||||||
|
@ -335,6 +333,7 @@ int YateH323Connection::s_total = 0;
|
||||||
int H323MsgThread::s_count = 0;
|
int H323MsgThread::s_count = 0;
|
||||||
int H323MsgThread::s_routed = 0;
|
int H323MsgThread::s_routed = 0;
|
||||||
|
|
||||||
|
|
||||||
bool H323MsgThread::route()
|
bool H323MsgThread::route()
|
||||||
{
|
{
|
||||||
Debug(DebugAll,"Routing thread for %s [%p]",m_id.c_str(),this);
|
Debug(DebugAll,"Routing thread for %s [%p]",m_id.c_str(),this);
|
||||||
|
@ -345,7 +344,7 @@ bool H323MsgThread::route()
|
||||||
bool ok = Engine::dispatch(m_msg) && !m_msg->retValue().null();
|
bool ok = Engine::dispatch(m_msg) && !m_msg->retValue().null();
|
||||||
YateH323Connection *conn = hplugin.findConnectionLock(m_id);
|
YateH323Connection *conn = hplugin.findConnectionLock(m_id);
|
||||||
if (!conn) {
|
if (!conn) {
|
||||||
Debug(DebugMild,"YateH323Connection '%s' wanished while routing!",m_id.c_str());
|
Debug(DebugMild,"YateH323Connection '%s' vanished while routing!",m_id.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
|
@ -381,8 +380,6 @@ void H323MsgThread::run()
|
||||||
s_count++;
|
s_count++;
|
||||||
s_route.unlock();
|
s_route.unlock();
|
||||||
Debug(DebugAll,"Started routing thread for %s [%p]",m_id.c_str(),this);
|
Debug(DebugAll,"Started routing thread for %s [%p]",m_id.c_str(),this);
|
||||||
m_mutex.lock();
|
|
||||||
m_mutex.unlock();
|
|
||||||
bool ok = route();
|
bool ok = route();
|
||||||
s_route.lock();
|
s_route.lock();
|
||||||
s_count--;
|
s_count--;
|
||||||
|
@ -438,6 +435,10 @@ YateH323EndPoint::~YateH323EndPoint()
|
||||||
H323Connection *YateH323EndPoint::CreateConnection(unsigned callReference,
|
H323Connection *YateH323EndPoint::CreateConnection(unsigned callReference,
|
||||||
void *userData, H323Transport *transport, H323SignalPDU *setupPDU)
|
void *userData, H323Transport *transport, H323SignalPDU *setupPDU)
|
||||||
{
|
{
|
||||||
|
if (Engine::exiting()) {
|
||||||
|
Debug(DebugWarn,"Refusing new connection, engine is exiting");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (s_maxconns > 0) {
|
if (s_maxconns > 0) {
|
||||||
s_calls.lock();
|
s_calls.lock();
|
||||||
int cnt = hplugin.calls().count();
|
int cnt = hplugin.calls().count();
|
||||||
|
@ -579,7 +580,8 @@ YateH323Connection::YateH323Connection(YateH323EndPoint &endpoint,
|
||||||
|
|
||||||
YateH323Connection::~YateH323Connection()
|
YateH323Connection::~YateH323Connection()
|
||||||
{
|
{
|
||||||
Debug(DebugAll,"YateH323Connection::~YateH323Connection() [%p]",this);
|
Debug(DebugAll,"YateH323Connection::~YateH323Connection() %s %s [%p]",
|
||||||
|
m_status.c_str(),m_id.c_str(),this);
|
||||||
setStatus("destroyed");
|
setStatus("destroyed");
|
||||||
s_calls.lock();
|
s_calls.lock();
|
||||||
hplugin.calls().remove(this,false);
|
hplugin.calls().remove(this,false);
|
||||||
|
@ -591,7 +593,8 @@ YateH323Connection::~YateH323Connection()
|
||||||
H323Connection::AnswerCallResponse YateH323Connection::OnAnswerCall(const PString &caller,
|
H323Connection::AnswerCallResponse YateH323Connection::OnAnswerCall(const PString &caller,
|
||||||
const H323SignalPDU &setupPDU, H323SignalPDU &connectPDU)
|
const H323SignalPDU &setupPDU, H323SignalPDU &connectPDU)
|
||||||
{
|
{
|
||||||
Debug(DebugInfo,"YateH323Connection::OnAnswerCall caller='%s' [%p]",(const char *)caller,this);
|
Debug(DebugInfo,"YateH323Connection::OnAnswerCall caller='%s' in %s [%p]",
|
||||||
|
(const char *)caller,m_id.c_str(),this);
|
||||||
setStatus("incoming");
|
setStatus("incoming");
|
||||||
|
|
||||||
if (Engine::exiting()) {
|
if (Engine::exiting()) {
|
||||||
|
@ -640,14 +643,12 @@ H323Connection::AnswerCallResponse YateH323Connection::OnAnswerCall(const PStrin
|
||||||
m->addParam("calledname",s);
|
m->addParam("calledname",s);
|
||||||
#endif
|
#endif
|
||||||
H323MsgThread *t = new H323MsgThread(m,id());
|
H323MsgThread *t = new H323MsgThread(m,id());
|
||||||
if (t->error()) {
|
if (!t->startup()) {
|
||||||
Debug(DebugWarn,"Error starting routing thread! [%p]",this);
|
Debug(DebugWarn,"Error starting routing thread! [%p]",this);
|
||||||
t->resume();
|
|
||||||
delete t;
|
delete t;
|
||||||
setStatus("dropped");
|
setStatus("dropped");
|
||||||
return H323Connection::AnswerCallDenied;
|
return H323Connection::AnswerCallDenied;
|
||||||
}
|
}
|
||||||
t->resume();
|
|
||||||
return H323Connection::AnswerCallDeferred;
|
return H323Connection::AnswerCallDeferred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1305,19 +1306,26 @@ YateH323Connection *H323Plugin::findConnectionLock(const char *id)
|
||||||
{
|
{
|
||||||
s_calls.lock();
|
s_calls.lock();
|
||||||
ObjList *l = &m_calls;
|
ObjList *l = &m_calls;
|
||||||
for (; l; l=l->next()) {
|
while (l) {
|
||||||
YateH323Connection *c = static_cast<YateH323Connection *>(l->get());
|
YateH323Connection *c = static_cast<YateH323Connection *>(l->get());
|
||||||
|
l=l->next();
|
||||||
if (c && (c->id() == id)) {
|
if (c && (c->id() == id)) {
|
||||||
if (c->TryLock() > 0) {
|
int res = c->TryLock();
|
||||||
|
if (res > 0) {
|
||||||
s_calls.unlock();
|
s_calls.unlock();
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
else {
|
else if (res < 0) {
|
||||||
// Yield and try scanning the list again
|
// Connection locked - yield and try scanning the list again
|
||||||
l = &m_calls;
|
|
||||||
s_calls.unlock();
|
s_calls.unlock();
|
||||||
Thread::yield();
|
Thread::yield();
|
||||||
s_calls.lock();
|
s_calls.lock();
|
||||||
|
l = &m_calls;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Connection shutting down - we can't lock it anymore
|
||||||
|
s_calls.unlock();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1325,13 +1333,19 @@ YateH323Connection *H323Plugin::findConnectionLock(const char *id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool H323Plugin::isBusy() const
|
||||||
|
{
|
||||||
|
return (m_calls.count() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
void H323Plugin::initialize()
|
void H323Plugin::initialize()
|
||||||
{
|
{
|
||||||
Output("Initializing module H.323 - based on OpenH323-" OPENH323_VERSION);
|
Output("Initializing module H.323 - based on OpenH323-" OPENH323_VERSION);
|
||||||
s_cfg = Engine::configFile("h323chan");
|
s_cfg = Engine::configFile("h323chan");
|
||||||
s_cfg.load();
|
s_cfg.load();
|
||||||
if (!m_process)
|
if (!m_process){
|
||||||
m_process = new H323Process;
|
m_process = new H323Process;
|
||||||
|
}
|
||||||
s_maxqueue = s_cfg.getIntValue("incoming","maxqueue",5);
|
s_maxqueue = s_cfg.getIntValue("incoming","maxqueue",5);
|
||||||
s_maxconns = s_cfg.getIntValue("ep","maxconns",0);
|
s_maxconns = s_cfg.getIntValue("ep","maxconns",0);
|
||||||
int dbg=s_cfg.getIntValue("general","debug");
|
int dbg=s_cfg.getIntValue("general","debug");
|
||||||
|
|
|
@ -99,7 +99,7 @@ public:
|
||||||
YateIAXConnection *findconn(iax_session *session);
|
YateIAXConnection *findconn(iax_session *session);
|
||||||
YateIAXConnection *findconn(const String& ourcallid);
|
YateIAXConnection *findconn(const String& ourcallid);
|
||||||
void handleEvent(iax_event *event);
|
void handleEvent(iax_event *event);
|
||||||
|
|
||||||
inline ObjList &calls()
|
inline ObjList &calls()
|
||||||
{ return m_calls; }
|
{ return m_calls; }
|
||||||
private:
|
private:
|
||||||
|
@ -138,6 +138,7 @@ public:
|
||||||
IAXPlugin();
|
IAXPlugin();
|
||||||
virtual ~IAXPlugin();
|
virtual ~IAXPlugin();
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
virtual bool isBusy() const;
|
||||||
void cleanup();
|
void cleanup();
|
||||||
YateIAXEndPoint *m_endpoint;
|
YateIAXEndPoint *m_endpoint;
|
||||||
private:
|
private:
|
||||||
|
@ -995,6 +996,10 @@ IAXPlugin::~IAXPlugin()
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IAXPlugin::isBusy() const
|
||||||
|
{
|
||||||
|
return m_endpoint && (m_endpoint->calls().count() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
void IAXPlugin::initialize()
|
void IAXPlugin::initialize()
|
||||||
{
|
{
|
||||||
|
@ -1005,6 +1010,7 @@ void IAXPlugin::initialize()
|
||||||
if (!YateIAXEndPoint::Init())
|
if (!YateIAXEndPoint::Init())
|
||||||
return;
|
return;
|
||||||
m_endpoint = new YateIAXEndPoint;
|
m_endpoint = new YateIAXEndPoint;
|
||||||
|
m_endpoint->startup();
|
||||||
}
|
}
|
||||||
YateIAXEndPoint::Setup();
|
YateIAXEndPoint::Setup();
|
||||||
if (m_first) {
|
if (m_first) {
|
||||||
|
|
|
@ -115,6 +115,7 @@ class OssPlugin : public Plugin
|
||||||
public:
|
public:
|
||||||
OssPlugin();
|
OssPlugin();
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
virtual bool isBusy() const;
|
||||||
private:
|
private:
|
||||||
OssHandler *m_handler;
|
OssHandler *m_handler;
|
||||||
};
|
};
|
||||||
|
@ -477,6 +478,11 @@ void OssPlugin::initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OssPlugin::isBusy() const
|
||||||
|
{
|
||||||
|
return (s_chan != 0);
|
||||||
|
}
|
||||||
|
|
||||||
INIT_PLUGIN(OssPlugin);
|
INIT_PLUGIN(OssPlugin);
|
||||||
|
|
||||||
/* vi: set ts=8 sw=4 sts=4 noet: */
|
/* vi: set ts=8 sw=4 sts=4 noet: */
|
||||||
|
|
|
@ -77,6 +77,7 @@ public:
|
||||||
RManager();
|
RManager();
|
||||||
~RManager();
|
~RManager();
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
virtual bool isBusy() const;
|
||||||
private:
|
private:
|
||||||
bool m_first;
|
bool m_first;
|
||||||
};
|
};
|
||||||
|
@ -115,7 +116,9 @@ void RManagerThread::run()
|
||||||
Connection *Connection::checkCreate(int sock)
|
Connection *Connection::checkCreate(int sock)
|
||||||
{
|
{
|
||||||
// should check IP address here
|
// should check IP address here
|
||||||
return new Connection(sock);
|
Connection *conn = new Connection(sock);
|
||||||
|
conn->startup();
|
||||||
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection(int sock)
|
Connection::Connection(int sock)
|
||||||
|
@ -404,6 +407,11 @@ RManager::~RManager()
|
||||||
Debugger::setIntOut(0);
|
Debugger::setIntOut(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RManager::isBusy() const
|
||||||
|
{
|
||||||
|
return (connectionlist.count() != 0);
|
||||||
|
}
|
||||||
|
|
||||||
void RManager::initialize()
|
void RManager::initialize()
|
||||||
{
|
{
|
||||||
Output("Initializing module RManager");
|
Output("Initializing module RManager");
|
||||||
|
@ -448,7 +456,8 @@ void RManager::initialize()
|
||||||
if (m_first) {
|
if (m_first) {
|
||||||
m_first = false;
|
m_first = false;
|
||||||
Engine::self()->setHook(postHook);
|
Engine::self()->setHook(postHook);
|
||||||
new RManagerThread;
|
RManagerThread *mt = new RManagerThread;
|
||||||
|
mt->startup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -475,6 +475,7 @@ public:
|
||||||
ZaptelPlugin();
|
ZaptelPlugin();
|
||||||
virtual ~ZaptelPlugin();
|
virtual ~ZaptelPlugin();
|
||||||
virtual void initialize();
|
virtual void initialize();
|
||||||
|
virtual bool isBusy() const;
|
||||||
PriSpan *findSpan(int chan);
|
PriSpan *findSpan(int chan);
|
||||||
ZapChan *findChan(const char *id);
|
ZapChan *findChan(const char *id);
|
||||||
ZapChan *findChan(int first = -1, int last = -1);
|
ZapChan *findChan(int first = -1, int last = -1);
|
||||||
|
@ -501,7 +502,9 @@ PriSpan *PriSpan::create(int span, int chan1, int nChans, int dChan, bool isNet,
|
||||||
::close(fd);
|
::close(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return new PriSpan(p,span,chan1,nChans,dChan,fd,dialPlan,presentation);
|
PriSpan *ps = new PriSpan(p,span,chan1,nChans,dChan,fd,dialPlan,presentation);
|
||||||
|
ps->startup();
|
||||||
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pri *PriSpan::makePri(int fd, int dchan, int nettype, int swtype,
|
struct pri *PriSpan::makePri(int fd, int dchan, int nettype, int swtype,
|
||||||
|
@ -1339,6 +1342,22 @@ ZapChan *ZaptelPlugin::findChan(int first, int last)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ZaptelPlugin::isBusy() const
|
||||||
|
{
|
||||||
|
const ObjList *l = &m_spans;
|
||||||
|
for (; l; l=l->next()) {
|
||||||
|
PriSpan *s = static_cast<PriSpan *>(l->get());
|
||||||
|
if (s) {
|
||||||
|
for (int n=1; n<=s->chans(); n++) {
|
||||||
|
ZapChan *c = s->getChan(n);
|
||||||
|
if (c && c->inUse())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ZaptelPlugin::initialize()
|
void ZaptelPlugin::initialize()
|
||||||
{
|
{
|
||||||
Output("Initializing module Zaptel");
|
Output("Initializing module Zaptel");
|
||||||
|
|
|
@ -5,7 +5,7 @@ CC := g++ -Wall
|
||||||
SED := sed
|
SED := sed
|
||||||
DEFS :=
|
DEFS :=
|
||||||
INCLUDES := -I@top_srcdir@
|
INCLUDES := -I@top_srcdir@
|
||||||
CFLAGS := -O0 @MODULE_CFLAGS@
|
CFLAGS := -O0 @MODULE_CFLAGS@ @INLINE_FLAGS@
|
||||||
LDFLAGS:= -L.. -lyate
|
LDFLAGS:= -L.. -lyate
|
||||||
MODFLAGS:= @MODULE_LDFLAGS@
|
MODFLAGS:= @MODULE_LDFLAGS@
|
||||||
MODSTRIP:= @MODULE_SYMBOLS@
|
MODSTRIP:= @MODULE_SYMBOLS@
|
||||||
|
|
|
@ -86,8 +86,10 @@ RandPlugin::RandPlugin()
|
||||||
void RandPlugin::initialize()
|
void RandPlugin::initialize()
|
||||||
{
|
{
|
||||||
Output("Initializing module RandPlugin");
|
Output("Initializing module RandPlugin");
|
||||||
if (!m_thread)
|
if (!m_thread) {
|
||||||
m_thread = new RandThread;
|
m_thread = new RandThread;
|
||||||
|
m_thread->startup();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_PLUGIN(RandPlugin);
|
INIT_PLUGIN(RandPlugin);
|
||||||
|
|
|
@ -87,7 +87,8 @@ void TestPlugin1::initialize()
|
||||||
m_first = false;
|
m_first = false;
|
||||||
for (int i=0; i<n; i++) {
|
for (int i=0; i<n; i++) {
|
||||||
::usleep(10000);
|
::usleep(10000);
|
||||||
new TestThread;
|
TestThread *t = new TestThread;
|
||||||
|
t->startup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
21
yatengine.h
21
yatengine.h
|
@ -1590,6 +1590,12 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void cleanup();
|
virtual void cleanup();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually starts running the new thread which lingers after creation
|
||||||
|
* @return True if an error occured, false if started ok
|
||||||
|
*/
|
||||||
|
bool startup();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the thread creation failed
|
* Check if the thread creation failed
|
||||||
* @return True if an error occured, false if created ok
|
* @return True if an error occured, false if created ok
|
||||||
|
@ -1598,7 +1604,7 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the thread is running or not
|
* Check if the thread is running or not
|
||||||
* @return True if running, false if it has terminated
|
* @return True if running, false if it has terminated or no startup called
|
||||||
*/
|
*/
|
||||||
bool running() const;
|
bool running() const;
|
||||||
|
|
||||||
|
@ -1774,6 +1780,13 @@ public:
|
||||||
* Initialize the plugin after it was loaded and registered.
|
* Initialize the plugin after it was loaded and registered.
|
||||||
*/
|
*/
|
||||||
virtual void initialize() = 0;
|
virtual void initialize() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the module is actively used.
|
||||||
|
* @return True if the plugin is in use, false if should be ok to restart
|
||||||
|
*/
|
||||||
|
virtual bool isBusy() const
|
||||||
|
{ return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1922,6 +1935,12 @@ public:
|
||||||
inline void setHook(void (*hookFunc)(Message &, bool) = 0)
|
inline void setHook(void (*hookFunc)(Message &, bool) = 0)
|
||||||
{ m_dispatcher.setHook(hookFunc); }
|
{ m_dispatcher.setHook(hookFunc); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a count of plugins that are actively in use
|
||||||
|
* @return Count of plugins in use
|
||||||
|
*/
|
||||||
|
int usedPlugins();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Destroys the engine and everything. You must not call it directly,
|
* Destroys the engine and everything. You must not call it directly,
|
||||||
|
|
|
@ -324,9 +324,10 @@ public:
|
||||||
virtual ~ThreadedSource();
|
virtual ~ThreadedSource();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the worker thread
|
* Starts the worker thread
|
||||||
|
* @return True if started, false if an error occured
|
||||||
*/
|
*/
|
||||||
void start(const char *name = "ThreadedSource");
|
bool start(const char *name = "ThreadedSource");
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue