mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-06 04:11:52 +00:00
indent pass 2
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@8689 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
@@ -3,336 +3,317 @@
|
||||
#define sanity_check(x) do { if (!session) { switch_log_printf(SWITCH_CHANNEL_LOG,SWITCH_LOG_ERROR, "session is not initalized\n"); return x;}} while(0)
|
||||
#define init_vars() do { caller_profile.source = "mod_python"; swapstate = S_SWAPPED_IN; } while(0)
|
||||
|
||||
PySession::PySession() : CoreSession()
|
||||
PySession::PySession():CoreSession()
|
||||
{
|
||||
init_vars();
|
||||
}
|
||||
|
||||
PySession::PySession(char *uuid) : CoreSession(uuid)
|
||||
PySession::PySession(char *uuid):CoreSession(uuid)
|
||||
{
|
||||
init_vars();
|
||||
}
|
||||
|
||||
PySession::PySession(switch_core_session_t *new_session) : CoreSession(new_session)
|
||||
PySession::PySession(switch_core_session_t *new_session):CoreSession(new_session)
|
||||
{
|
||||
init_vars();
|
||||
}
|
||||
|
||||
|
||||
void PySession::setDTMFCallback(PyObject *pyfunc, char *funcargs)
|
||||
void PySession::setDTMFCallback(PyObject * pyfunc, char *funcargs)
|
||||
{
|
||||
sanity_check();
|
||||
sanity_check();
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF function is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setDTMFCallback((void *) pyfunc, funcargs);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PySession::setHangupHook(PyObject * pyfunc)
|
||||
{
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hangup hook is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
// without this Py_XINCREF, there will be segfaults. basically the python
|
||||
// interpreter will not know that it should not GC this object.
|
||||
// callback example: http://docs.python.org/ext/callingPython.html
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setHangupHook((void *) pyfunc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PySession::check_hangup_hook()
|
||||
{
|
||||
PyObject *func;
|
||||
PyObject *result;
|
||||
char *resultStr;
|
||||
bool did_swap_in = false;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
|
||||
"check_hangup_hook has been DISABLED, please do not use hangup hooks in python code until further notice!\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "DTMF function is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setDTMFCallback((void *) pyfunc, funcargs);
|
||||
|
||||
/*! NEEDS TO BE FIXED:
|
||||
|
||||
// The did_swap_in boolean was added to fix the following problem:
|
||||
// Design flaw - we swap in threadstate based on the assumption that thread state
|
||||
// is currently _swapped out_ when this hangup hook is called. However, nothing known to
|
||||
// guarantee that, and if thread state is already swapped in when this is invoked,
|
||||
// bad things will happen.
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
if (on_hangup == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "on_hangup is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
func = (PyObject *) on_hangup;
|
||||
|
||||
// TODO: to match js implementation, should pass the _python_ PySession
|
||||
// object instance wrapping this C++ PySession instance. but how do we do that?
|
||||
// for now, pass the uuid since its better than nothing
|
||||
PyObject* func_arg = Py_BuildValue("(s)", uuid);
|
||||
|
||||
result = PyEval_CallObject(func, func_arg);
|
||||
Py_XDECREF(func_arg);
|
||||
|
||||
if (result) {
|
||||
resultStr = (char *) PyString_AsString(result);
|
||||
// currently just ignore the result
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to call python hangup callback\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(result);
|
||||
*/
|
||||
}
|
||||
|
||||
switch_status_t PySession::run_dtmf_callback(void *input, switch_input_type_t itype)
|
||||
{
|
||||
|
||||
PyObject *func, *arglist;
|
||||
PyObject *pyresult;
|
||||
PyObject *headerdict;
|
||||
|
||||
char *resultStr;
|
||||
char *funcargs;
|
||||
switch_file_handle_t *fh = NULL;
|
||||
bool did_swap_in = false;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback\n");
|
||||
|
||||
|
||||
if (!cb_state.function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
func = (PyObject *) cb_state.function;
|
||||
if (!func) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state->function is NOT null\n");
|
||||
}
|
||||
if (!PyCallable_Check(func)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "function not callable\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
funcargs = (char *) cb_state.funcargs;
|
||||
|
||||
if (itype == SWITCH_INPUT_TYPE_DTMF) {
|
||||
|
||||
arglist = Py_BuildValue("(sis)", input, itype, funcargs);
|
||||
} else if (itype == SWITCH_INPUT_TYPE_EVENT) {
|
||||
// DUNNO if this is correct in the case we have an event
|
||||
// will be of type switch_event_t *event;
|
||||
// http://www.freeswitch.org/docs/structswitch__event.html
|
||||
switch_event_t *event = (switch_event_t *) input;
|
||||
arglist = Py_BuildValue("({s:s}is)", "body", event->body, itype, funcargs);
|
||||
|
||||
// build a dictionary with all the headers
|
||||
|
||||
switch_event_header_t *hp;
|
||||
headerdict = PyDict_New();
|
||||
for (hp = event->headers; hp; hp = hp->next) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding event header to result");
|
||||
|
||||
// TODO: create PyObject pointers for name and value
|
||||
// and explicitly decref them. all ref counting stuff is
|
||||
// a mess and needs to be tested and looked at closer.
|
||||
PyDict_SetItem(headerdict, Py_BuildValue("s", hp->name), Py_BuildValue("s", hp->value));
|
||||
|
||||
}
|
||||
|
||||
// add it to the main event dictionary (first arg in list)
|
||||
// under key 'headers'
|
||||
PyObject *dict = PyTuple_GetItem(arglist, 0);
|
||||
PyDict_SetItemString(dict, "headers", headerdict);
|
||||
|
||||
Py_XDECREF(headerdict);
|
||||
|
||||
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown input type: %d\n", itype);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!arglist) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error building arglist");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
pyresult = PyEval_CallObject(func, arglist);
|
||||
|
||||
|
||||
Py_XDECREF(arglist); // Trash arglist
|
||||
|
||||
if (pyresult && pyresult != Py_None) {
|
||||
resultStr = (char *) PyString_AsString(pyresult);
|
||||
switch_status_t cbresult = process_callback_result(resultStr);
|
||||
return cbresult;
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Python callback\n returned None");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(pyresult);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
bool PySession::begin_allow_threads(void)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::begin_allow_threads() called\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
// swap out threadstate and store in instance variable
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
// so lets assume the thread state was swapped in when the python script was started,
|
||||
// therefore swapin_tstate will be NULL (because there is nothing to swap in, since its
|
||||
// _already_ swapped in.)
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-out!\n");
|
||||
swapin_tstate = PyEval_SaveThread();
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
// give future swapper-inners something to actually swap in
|
||||
switch_channel_set_private(channel, "SwapInThreadState", (void *) swapin_tstate);
|
||||
cb_state.threadState = threadState; // TODO: get rid of this
|
||||
args.buf = &cb_state;
|
||||
ap = &args;
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// currently swapped out
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool PySession::end_allow_threads(void)
|
||||
{
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::end_allow_threads() called\n");
|
||||
// swap in threadstate from instance variable saved earlier
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
return false;
|
||||
} else {
|
||||
// currently swapped out
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-in!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
PyEval_RestoreThread(swapin_tstate);
|
||||
// dont give any swapper-inners the opportunity to do a double swap
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PySession::setHangupHook(PyObject *pyfunc) {
|
||||
void PySession::hangup(char *cause)
|
||||
{
|
||||
|
||||
if (!PyCallable_Check(pyfunc)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Hangup hook is not a python function.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// without this Py_XINCREF, there will be segfaults. basically the python
|
||||
// interpreter will not know that it should not GC this object.
|
||||
// callback example: http://docs.python.org/ext/callingPython.html
|
||||
Py_XINCREF(pyfunc);
|
||||
CoreSession::setHangupHook((void *) pyfunc);
|
||||
// since we INCREF'd this function pointer earlier (so the py gc didnt reclaim it)
|
||||
// we have to DECREF it, or else the PySession dtor will never get called and
|
||||
// a zombie channel will be left over using up resources
|
||||
|
||||
if (cb_state.function != NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "xdecref on cb_state_function\n");
|
||||
PyObject *func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state.function is null\n");
|
||||
}
|
||||
|
||||
|
||||
CoreSession::hangup(cause);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PySession::check_hangup_hook() {
|
||||
PyObject *func;
|
||||
PyObject *result;
|
||||
char *resultStr;
|
||||
bool did_swap_in = false;
|
||||
PySession::~PySession()
|
||||
{
|
||||
// Should we do any cleanup here?
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession started\n");
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "check_hangup_hook has been DISABLED, please do not use hangup hooks in python code until further notice!\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
/*! NEEDS TO BE FIXED:
|
||||
|
||||
// The did_swap_in boolean was added to fix the following problem:
|
||||
// Design flaw - we swap in threadstate based on the assumption that thread state
|
||||
// is currently _swapped out_ when this hangup hook is called. However, nothing known to
|
||||
// guarantee that, and if thread state is already swapped in when this is invoked,
|
||||
// bad things will happen.
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
if (on_hangup == NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "on_hangup is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
func = (PyObject *) on_hangup;
|
||||
|
||||
// TODO: to match js implementation, should pass the _python_ PySession
|
||||
// object instance wrapping this C++ PySession instance. but how do we do that?
|
||||
// for now, pass the uuid since its better than nothing
|
||||
PyObject* func_arg = Py_BuildValue("(s)", uuid);
|
||||
|
||||
result = PyEval_CallObject(func, func_arg);
|
||||
Py_XDECREF(func_arg);
|
||||
|
||||
if (result) {
|
||||
resultStr = (char *) PyString_AsString(result);
|
||||
// currently just ignore the result
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to call python hangup callback\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "check hangup hook begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(result);
|
||||
*/
|
||||
}
|
||||
|
||||
switch_status_t PySession::run_dtmf_callback(void *input,
|
||||
switch_input_type_t itype) {
|
||||
|
||||
PyObject *func, *arglist;
|
||||
PyObject *pyresult;
|
||||
PyObject *headerdict;
|
||||
|
||||
char *resultStr;
|
||||
char *funcargs;
|
||||
switch_file_handle_t *fh = NULL;
|
||||
bool did_swap_in = false;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback\n");
|
||||
if (on_hangup) {
|
||||
PyObject *func = (PyObject *) on_hangup;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
|
||||
if (!cb_state.function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
if (cb_state.function != NULL) {
|
||||
PyObject *func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
func = (PyObject *) cb_state.function;
|
||||
if (!func) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "cb_state->function is null\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state->function is NOT null\n");
|
||||
}
|
||||
if (!PyCallable_Check(func)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "function not callable\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
funcargs = (char *) cb_state.funcargs;
|
||||
|
||||
if (itype == SWITCH_INPUT_TYPE_DTMF) {
|
||||
|
||||
arglist = Py_BuildValue("(sis)", input, itype, funcargs);
|
||||
}
|
||||
else if (itype == SWITCH_INPUT_TYPE_EVENT) {
|
||||
// DUNNO if this is correct in the case we have an event
|
||||
// will be of type switch_event_t *event;
|
||||
// http://www.freeswitch.org/docs/structswitch__event.html
|
||||
switch_event_t *event = (switch_event_t *) input;
|
||||
arglist = Py_BuildValue("({s:s}is)",
|
||||
"body", event->body,
|
||||
itype,
|
||||
funcargs);
|
||||
|
||||
// build a dictionary with all the headers
|
||||
|
||||
switch_event_header_t *hp;
|
||||
headerdict = PyDict_New();
|
||||
for (hp = event->headers; hp; hp = hp->next) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding event header to result");
|
||||
|
||||
// TODO: create PyObject pointers for name and value
|
||||
// and explicitly decref them. all ref counting stuff is
|
||||
// a mess and needs to be tested and looked at closer.
|
||||
PyDict_SetItem(headerdict,
|
||||
Py_BuildValue("s", hp->name),
|
||||
Py_BuildValue("s", hp->value));
|
||||
|
||||
}
|
||||
|
||||
// add it to the main event dictionary (first arg in list)
|
||||
// under key 'headers'
|
||||
PyObject *dict = PyTuple_GetItem(arglist, 0);
|
||||
PyDict_SetItemString(dict,
|
||||
"headers",
|
||||
headerdict);
|
||||
|
||||
Py_XDECREF(headerdict);
|
||||
|
||||
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown input type: %d\n", itype);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
|
||||
if (!arglist) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error building arglist");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback end_allow_threads\n");
|
||||
did_swap_in = end_allow_threads();
|
||||
|
||||
pyresult = PyEval_CallObject(func, arglist);
|
||||
|
||||
|
||||
Py_XDECREF(arglist); // Trash arglist
|
||||
|
||||
if (pyresult && pyresult != Py_None) {
|
||||
resultStr = (char *) PyString_AsString(pyresult);
|
||||
switch_status_t cbresult = process_callback_result(resultStr);
|
||||
return cbresult;
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Python callback\n returned None");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "run_dtmf_callback begin_allow_threads\n");
|
||||
if (did_swap_in) {
|
||||
begin_allow_threads();
|
||||
}
|
||||
|
||||
Py_XDECREF(pyresult);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession finished\n");
|
||||
|
||||
}
|
||||
|
||||
bool PySession::begin_allow_threads(void) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::begin_allow_threads() called\n");
|
||||
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// swap out threadstate and store in instance variable
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
// so lets assume the thread state was swapped in when the python script was started,
|
||||
// therefore swapin_tstate will be NULL (because there is nothing to swap in, since its
|
||||
// _already_ swapped in.)
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-out!\n");
|
||||
swapin_tstate = PyEval_SaveThread();
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
// give future swapper-inners something to actually swap in
|
||||
switch_channel_set_private(channel, "SwapInThreadState", (void *) swapin_tstate);
|
||||
cb_state.threadState = threadState; // TODO: get rid of this
|
||||
args.buf = &cb_state;
|
||||
ap = &args;
|
||||
return true;
|
||||
|
||||
}
|
||||
else {
|
||||
// currently swapped out
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool PySession::end_allow_threads(void) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::end_allow_threads() called\n");
|
||||
// swap in threadstate from instance variable saved earlier
|
||||
if (!session) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No valid session\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
PyThreadState *swapin_tstate = (PyThreadState *) switch_channel_get_private(channel, "SwapInThreadState");
|
||||
if (swapin_tstate == NULL) {
|
||||
// currently swapped in
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// currently swapped out
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Threadstate swap-in!\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "swapin_tstate: %p\n", swapin_tstate);
|
||||
PyEval_RestoreThread(swapin_tstate);
|
||||
// dont give any swapper-inners the opportunity to do a double swap
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PySession::hangup(char *cause) {
|
||||
|
||||
|
||||
// since we INCREF'd this function pointer earlier (so the py gc didnt reclaim it)
|
||||
// we have to DECREF it, or else the PySession dtor will never get called and
|
||||
// a zombie channel will be left over using up resources
|
||||
|
||||
if (cb_state.function != NULL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "xdecref on cb_state_function\n");
|
||||
PyObject * func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "cb_state.function is null\n");
|
||||
}
|
||||
|
||||
|
||||
CoreSession::hangup(cause);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PySession::~PySession() {
|
||||
// Should we do any cleanup here?
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession started\n");
|
||||
|
||||
if (on_hangup) {
|
||||
PyObject * func = (PyObject *) on_hangup;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
|
||||
if (cb_state.function != NULL) {
|
||||
PyObject * func = (PyObject *) cb_state.function;
|
||||
Py_XDECREF(func);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "PySession::~PySession finished\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
{
|
||||
PyThreadState *tstate = NULL;
|
||||
char *dupargs = NULL;
|
||||
char *argv[128] = {0};
|
||||
char *argv[128] = { 0 };
|
||||
int argc;
|
||||
int lead = 0;
|
||||
char *script = NULL;
|
||||
@@ -68,16 +68,16 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (args) {
|
||||
dupargs = strdup(args);
|
||||
dupargs = strdup(args);
|
||||
} else {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(dupargs != NULL);
|
||||
|
||||
|
||||
if (!(argc = switch_separate_string(dupargs, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No module name specified!\n");
|
||||
goto done;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No module name specified!\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
script = argv[0];
|
||||
@@ -87,80 +87,76 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
|
||||
tstate = PyThreadState_New(mainThreadState->interp);
|
||||
if (!tstate) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n");
|
||||
goto done;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error acquiring tstate\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
// swap in thread state
|
||||
PyEval_AcquireThread(tstate);
|
||||
if (session) {
|
||||
// record the fact that thread state is swapped in
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
// record the fact that thread state is swapped in
|
||||
switch_channel_t *channel = switch_core_session_get_channel(session);
|
||||
switch_channel_set_private(channel, "SwapInThreadState", NULL);
|
||||
}
|
||||
init_freeswitch();
|
||||
init_freeswitch();
|
||||
|
||||
// import the module
|
||||
module = PyImport_ImportModule( (char *) script);
|
||||
module = PyImport_ImportModule((char *) script);
|
||||
if (!module) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
// reload the module
|
||||
module = PyImport_ReloadModule(module);
|
||||
if (!module) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
// get the handler function to be called
|
||||
function = PyObject_GetAttrString(module, "handler");
|
||||
if (!function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define handler(uuid)\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
if (uuid) {
|
||||
// build a tuple to pass the args, the uuid of session
|
||||
arg = Py_BuildValue("(s)", uuid);
|
||||
if (!arg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error building args\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error importing module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
arg = PyTuple_New(1);
|
||||
PyObject *nada = Py_BuildValue("");
|
||||
PyTuple_SetItem(arg, 0, nada);
|
||||
// reload the module
|
||||
module = PyImport_ReloadModule(module);
|
||||
if (!module) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error reloading module\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
// get the handler function to be called
|
||||
function = PyObject_GetAttrString(module, "handler");
|
||||
if (!function) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Module does not define handler(uuid)\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
|
||||
if (uuid) {
|
||||
// build a tuple to pass the args, the uuid of session
|
||||
arg = Py_BuildValue("(s)", uuid);
|
||||
if (!arg) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error building args\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
goto done_swap_out;
|
||||
}
|
||||
} else {
|
||||
arg = PyTuple_New(1);
|
||||
PyObject *nada = Py_BuildValue("");
|
||||
PyTuple_SetItem(arg, 0, nada);
|
||||
}
|
||||
|
||||
// invoke the handler
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call python script \n");
|
||||
result = PyEval_CallObjectWithKeywords(function, arg, (PyObject *)NULL);
|
||||
result = PyEval_CallObjectWithKeywords(function, arg, (PyObject *) NULL);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Finished calling python script \n");
|
||||
|
||||
// check the result and print out any errors
|
||||
if (!result) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error calling python script\n");
|
||||
PyErr_Print();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
goto done_swap_out;
|
||||
|
||||
done:
|
||||
done:
|
||||
switch_safe_free(dupargs);
|
||||
|
||||
done_swap_out:
|
||||
done_swap_out:
|
||||
// decrement ref counts
|
||||
Py_XDECREF(module);
|
||||
Py_XDECREF(function);
|
||||
@@ -183,14 +179,12 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
PyThreadState *cur_tstate = PyThreadState_Get();
|
||||
PyThreadState_Clear(cur_tstate);
|
||||
PyEval_ReleaseThread(cur_tstate);
|
||||
PyThreadState_Delete(cur_tstate);
|
||||
}
|
||||
else {
|
||||
PyThreadState_Delete(cur_tstate);
|
||||
} else {
|
||||
// thread state is already swapped out, so, nothing for us to do
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "according to chan priv data, already swapped out \n");
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// they ran python script from cmd line, behave a bit differently (untested)
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "No session: Threadstate mod_python.c swap-out! \n");
|
||||
PyEval_ReleaseThread(tstate);
|
||||
@@ -203,8 +197,8 @@ static void eval_some_python(char *uuid, char *args, switch_core_session_t *sess
|
||||
|
||||
SWITCH_STANDARD_APP(python_function)
|
||||
{
|
||||
eval_some_python(switch_core_session_get_uuid(session), (char *)data, session);
|
||||
|
||||
eval_some_python(switch_core_session_get_uuid(session), (char *) data, session);
|
||||
|
||||
}
|
||||
|
||||
struct switch_py_thread {
|
||||
@@ -228,7 +222,7 @@ static void *SWITCH_THREAD_FUNC py_thread_run(switch_thread_t *thread, void *obj
|
||||
SWITCH_STANDARD_API(launch_python)
|
||||
{
|
||||
switch_thread_t *thread;
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
switch_threadattr_t *thd_attr = NULL;
|
||||
switch_memory_pool_t *pool;
|
||||
struct switch_py_thread *pt;
|
||||
|
||||
@@ -236,7 +230,7 @@ SWITCH_STANDARD_API(launch_python)
|
||||
stream->write_function(stream, "USAGE: %s\n", python_run_interface.syntax);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
switch_core_new_memory_pool(&pool);
|
||||
assert(pool != NULL);
|
||||
|
||||
@@ -245,11 +239,11 @@ SWITCH_STANDARD_API(launch_python)
|
||||
|
||||
pt->pool = pool;
|
||||
pt->args = switch_core_strdup(pt->pool, cmd);
|
||||
|
||||
switch_threadattr_create(&thd_attr, pt->pool);
|
||||
switch_threadattr_detach_set(thd_attr, 1);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
switch_thread_create(&thread, thd_attr, py_thread_run, pt, pt->pool);
|
||||
|
||||
switch_threadattr_create(&thd_attr, pt->pool);
|
||||
switch_threadattr_detach_set(thd_attr, 1);
|
||||
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
||||
switch_thread_create(&thread, thd_attr, py_thread_run, pt, pt->pool);
|
||||
|
||||
stream->write_function(stream, "OK\n");
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -290,7 +284,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_python_load)
|
||||
/* connect my internal structure to the blank pointer passed to me */
|
||||
*module_interface = &python_module_interface;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Python Framework Loading...\n");
|
||||
|
||||
|
||||
if (!Py_IsInitialized()) {
|
||||
|
||||
// initialize python system
|
||||
@@ -302,13 +296,13 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_python_load)
|
||||
// save threadstate since it's interp field will be needed
|
||||
// to create new threadstates, and will be needed for shutdown
|
||||
mainThreadState = PyThreadState_Get();
|
||||
|
||||
|
||||
// swap out threadstate since the call threads will create
|
||||
// their own and swap in their threadstate
|
||||
PyThreadState_Swap(NULL);
|
||||
PyThreadState_Swap(NULL);
|
||||
|
||||
// release GIL
|
||||
PyEval_ReleaseLock();
|
||||
PyEval_ReleaseLock();
|
||||
}
|
||||
|
||||
/* indicate that the module should continue to be loaded */
|
||||
@@ -319,18 +313,18 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_python_load)
|
||||
Called when the system shuts down*/
|
||||
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_python_shutdown)
|
||||
{
|
||||
PyInterpreterState *mainInterpreterState;
|
||||
PyThreadState *myThreadState;
|
||||
PyInterpreterState *mainInterpreterState;
|
||||
PyThreadState *myThreadState;
|
||||
|
||||
PyEval_AcquireLock();
|
||||
mainInterpreterState = mainThreadState->interp;
|
||||
myThreadState = PyThreadState_New(mainInterpreterState);
|
||||
PyThreadState_Swap(myThreadState);
|
||||
PyEval_ReleaseLock();
|
||||
PyEval_AcquireLock();
|
||||
mainInterpreterState = mainThreadState->interp;
|
||||
myThreadState = PyThreadState_New(mainInterpreterState);
|
||||
PyThreadState_Swap(myThreadState);
|
||||
PyEval_ReleaseLock();
|
||||
|
||||
Py_Finalize();
|
||||
PyEval_ReleaseLock();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
Py_Finalize();
|
||||
PyEval_ReleaseLock();
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -571,7 +571,7 @@ extern "C" {
|
||||
* type checking.
|
||||
*
|
||||
* Author : David Beazley (beazley@cs.uchicago.edu)
|
||||
************************************************************************//* Common SWIG API */
|
||||
************************************************************************//* Common SWIG API */
|
||||
#define SWIG_ConvertPtr(obj, pp, type, flags) SWIG_Python_ConvertPtr(obj, pp, type, flags)
|
||||
#define SWIG_NewPointerObj(p, type, flags) SWIG_Python_NewPointerObj(p, type, flags)
|
||||
#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags)
|
||||
@@ -583,11 +583,11 @@ extern "C" {
|
||||
#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer)
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Pointer declarations
|
||||
* ----------------------------------------------------------------------------- *//*
|
||||
Use SWIG_NO_COBJECT_TYPES to force the use of strings to represent
|
||||
C/C++ pointers in the python side. Very useful for debugging, but
|
||||
not always safe.
|
||||
*/
|
||||
* ----------------------------------------------------------------------------- *//*
|
||||
Use SWIG_NO_COBJECT_TYPES to force the use of strings to represent
|
||||
C/C++ pointers in the python side. Very useful for debugging, but
|
||||
not always safe.
|
||||
*/
|
||||
#if !defined(SWIG_NO_COBJECT_TYPES) && !defined(SWIG_COBJECT_TYPES)
|
||||
# define SWIG_COBJECT_TYPES
|
||||
#endif
|
||||
@@ -1538,8 +1538,7 @@ extern "C" {
|
||||
resultobj = Py_None;
|
||||
return resultobj;
|
||||
fail:return NULL;
|
||||
}
|
||||
static PyObject *_wrap_fs_core_init(PyObject * self, PyObject * args) {
|
||||
} static PyObject *_wrap_fs_core_init(PyObject * self, PyObject * args) {
|
||||
PyObject *resultobj = NULL;
|
||||
char *arg1 = (char *) 0;
|
||||
int result;
|
||||
@@ -2683,8 +2682,7 @@ extern "C" {
|
||||
SWIGINTERN PyObject *swig_varlink_repr(swig_varlinkobject * v) {
|
||||
v = v;
|
||||
return PyString_FromString("<Swig global variables>");
|
||||
}
|
||||
SWIGINTERN int swig_varlink_print(swig_varlinkobject * v, FILE * fp, int flags) {
|
||||
} SWIGINTERN int swig_varlink_print(swig_varlinkobject * v, FILE * fp, int flags) {
|
||||
swig_globalvar *var;
|
||||
flags = flags;
|
||||
fprintf(fp, "Swig global variables { ");
|
||||
|
||||
Reference in New Issue
Block a user