crash prevention

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@1281 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2006-04-27 21:09:58 +00:00
parent 24627a7a4b
commit 5ab733c606
5 changed files with 72 additions and 2 deletions

View File

@ -41,6 +41,9 @@
#ifdef __cplusplus
extern "C" {
#ifdef __FORMATBUG
}
#endif
#endif
#include <apr.h>
@ -48,6 +51,7 @@ extern "C" {
#include <apr_errno.h>
#include <apr_general.h>
#include <apr_thread_proc.h>
#include <apr_portable.h>
#include <apr_thread_mutex.h>
#include <apr_thread_cond.h>
#include <apr_thread_rwlock.h>
@ -257,6 +261,12 @@ typedef apr_thread_cond_t switch_thread_cond_t;
DoxyDefine(apr_status_t switch_thread_cond_create(switch_thread_cond_t **cond, switch_pool_t *pool);)
#define switch_thread_cond_create apr_thread_cond_create
typedef apr_os_thread_t switch_thread_id;
#define switch_thread_data_set apr_thread_data_set
#define switch_thread_data_get apr_thread_data_get
#define switch_thread_self apr_os_thread_current
/**
* Put the active calling thread to sleep until signaled to wake up. Each
* condition variable must be associated with a mutex, and that mutex must

View File

@ -514,6 +514,7 @@ typedef enum {
SWITCH_EVENT_UNPUBLISH - UnPublish
SWITCH_EVENT_TALK - Talking Detected
SWITCH_EVENT_NOTALK - Not Talking Detected
SWITCH_EVENT_SESSION_CRASH - Session Crashed
SWITCH_EVENT_ALL - All events at once
</pre>
@ -538,6 +539,7 @@ typedef enum {
SWITCH_EVENT_UNPUBLISH,
SWITCH_EVENT_TALK,
SWITCH_EVENT_NOTALK,
SWITCH_EVENT_SESSION_CRASH,
SWITCH_EVENT_ALL
} switch_event_t;

View File

@ -48,6 +48,13 @@ static switch_status on_dtmf(switch_core_session *session, char *dtmf, void *buf
}
static void disast_function(switch_core_session *session, char *data)
{
printf("%s WOOHOO\n", (char *) 42);
}
static void dirtest_function(switch_core_session *session, char *data)
{
char *var, *val;
@ -194,11 +201,19 @@ static const switch_state_handler_table state_handlers = {
/*.on_transmit */ NULL
};
static const switch_application_interface disast_application_interface = {
/*.interface_name */ "disast",
/*.application_function */ disast_function,
NULL, NULL, NULL,
/*.next*/ NULL
};
static const switch_application_interface tts_application_interface = {
/*.interface_name */ "tts",
/*.application_function */ tts_function,
NULL, NULL, NULL,
/*.next*/ NULL
/*.next*/ &disast_application_interface
};
static const switch_application_interface dirtest_application_interface = {

View File

@ -36,6 +36,7 @@
#define SWITCH_EVENT_QUEUE_LEN 256
#define SWITCH_SQL_QUEUE_LEN 2000
#define SWITCH_THREAD_JMP_KEY "JMP_KEY"
struct switch_core_session {
uint32_t id;
@ -83,6 +84,7 @@ struct switch_core_runtime {
uint32_t session_id;
apr_pool_t *memory_pool;
switch_hash *session_table;
switch_hash *stack_table;
switch_core_db *db;
switch_core_db *event_db;
const struct switch_state_handler_table *state_handlers[SWITCH_MAX_STATE_HANDLERS];
@ -1811,12 +1813,50 @@ SWITCH_DECLARE(unsigned int) switch_core_session_runing(switch_core_session *ses
return session->thread_running;
}
static int handle_fatality(int sig)
{
switch_thread_id thread_id;
jmp_buf *env;
if (sig && (thread_id = switch_thread_self()) && (env = (jmp_buf *) apr_hash_get(runtime.stack_table, &thread_id, sizeof(thread_id)))) {
longjmp(*env, sig);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Caught SEGV for unmapped thread!");
abort();
}
return 0;
}
SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
{
switch_channel_state state = CS_NEW, laststate = CS_HANGUP, midstate = CS_DONE;
const switch_endpoint_interface *endpoint_interface;
const switch_state_handler_table *driver_state_handler = NULL;
const switch_state_handler_table *application_state_handler = NULL;
switch_thread_id thread_id = switch_thread_self();
jmp_buf env;
int sig;
signal(SIGSEGV, (void *) handle_fatality);
signal(SIGFPE, (void *) handle_fatality);
#ifndef WIN32
signal(SIGBUS, (void *) handle_fatality);
#endif
if ((sig = setjmp(env)) != 0) {
switch_event *event;
if (switch_event_create(&event, SWITCH_EVENT_SESSION_CRASH) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(session->channel, event);
switch_event_fire(&event);
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Thread has crashed for channel %s\n", switch_channel_get_name(session->channel));
switch_channel_hangup(session->channel, SWITCH_CAUSE_CRASH);
} else {
apr_hash_set(runtime.stack_table, &thread_id, sizeof(thread_id), &env);
}
/*
Life of the channel. you have channel and pool in your session
@ -1850,7 +1890,6 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
int proceed = 1;
midstate = state;
switch (state) {
case CS_NEW: /* Just created, Waiting for first instructions */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) State NEW\n", switch_channel_get_name(session->channel));
@ -2091,6 +2130,8 @@ SWITCH_DECLARE(void) switch_core_session_run(switch_core_session *session)
}
}
apr_hash_set(runtime.stack_table, &thread_id, sizeof(thread_id), NULL);
session->thread_running = 0;
}
@ -2650,6 +2691,7 @@ SWITCH_DECLARE(switch_status) switch_core_init(char *console)
runtime.session_id = 1;
switch_core_hash_init(&runtime.session_table, runtime.memory_pool);
switch_core_hash_init(&runtime.stack_table, runtime.memory_pool);
time(&runtime.initiated);
return SWITCH_STATUS_SUCCESS;

View File

@ -102,6 +102,7 @@ static char *EVENT_NAMES[] = {
"UNPUBLISH",
"TALK",
"NOTALK",
"SESSION_CRASH",
"ALL"
};