superkaramba: fixed SEGV when loading python scripts.

This resolves issue #43.

Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
pull/44/head
Michele Calgaro 2 years ago
parent 2e211499d4
commit 5dab6232ef
Signed by: MicheleC
GPG Key ID: 2A75B7CA8ADED5CF

@ -310,7 +310,7 @@ karamba::karamba(TQString fn, TQString name, bool reloading, int instance,
move(xpos, ypos); move(xpos, ypos);
} }
haveUpdated = 0; haveUpdated = false;
this->setMouseTracking(true); this->setMouseTracking(true);
@ -1691,14 +1691,13 @@ void karamba::step()
if (pythonIface && pythonIface->isExtensionLoaded()) if (pythonIface && pythonIface->isExtensionLoaded())
{ {
if (haveUpdated == 0) if (!haveUpdated)
pythonIface->initWidget(this); pythonIface->initWidget(this);
else else
pythonIface->widgetUpdated(this); pythonIface->widgetUpdated(this);
} }
if (haveUpdated == 0) haveUpdated = true;
haveUpdated = 1;
} }
void karamba::widgetClosed() void karamba::widgetClosed()

@ -51,12 +51,7 @@ struct module_state {
PyObject *error; PyObject *error;
}; };
#if PY_MAJOR_VERSION >= 3
#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
#else
#define GETSTATE(m) (&_state)
static struct module_state _state;
#endif
static PyObject * static PyObject *
error_out(PyObject *m) { error_out(PyObject *m) {
@ -356,8 +351,6 @@ static PyMethodDef karamba_methods[] = {
{NULL, NULL, 0 ,NULL} {NULL, NULL, 0 ,NULL}
}; };
#if PY_MAJOR_VERSION >= 3
static int karamba_traverse(PyObject *m, visitproc visit, void *arg) { static int karamba_traverse(PyObject *m, visitproc visit, void *arg) {
Py_VISIT(GETSTATE(m)->error); Py_VISIT(GETSTATE(m)->error);
return 0; return 0;
@ -382,22 +375,18 @@ static struct PyModuleDef karambadef = {
#define INITERROR return NULL #define INITERROR return NULL
#else PyMODINIT_FUNC PyInit_karamba(void)
{
#define INITERROR return return PyModule_Create(&karambadef);
}
#endif
PyThreadState* KarambaPython::mainThreadState = 0; PyThreadState* KarambaPython::mainThreadState = 0;
KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading): KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading):
pythonThemeExtensionLoaded(false), pName(0), pModule(0), pDict(0) pythonThemeExtensionLoaded(false), pName(0), pModule(0), pDict(0)
{ {
PyThreadState* myThreadState;
char pypath[1024]; char pypath[1024];
getLock(&myThreadState);
// load the .py file for this .theme // load the .py file for this .theme
PyRun_SimpleString((char*)"import sys"); PyRun_SimpleString((char*)"import sys");
//Add theme path to python path so that we can find the python file //Add theme path to python path so that we can find the python file
@ -405,13 +394,7 @@ KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading):
PyRun_SimpleString(pypath); PyRun_SimpleString(pypath);
PyRun_SimpleString((char*)"sys.path.insert(0, '')"); PyRun_SimpleString((char*)"sys.path.insert(0, '')");
PyImport_AddModule((char*)"karamba"); pName = PyUnicode_FromString(theme.pythonModule().utf8());
#if PY_MAJOR_VERSION >= 3
PyModule_Create(&karambadef);
#else
Py_InitModule((char*)"karamba", karamba_methods);
#endif
pName = PyBytes_FromString(theme.pythonModule().ascii());
pModule = PyImport_Import(pName); pModule = PyImport_Import(pName);
fprintf(stderr, "%s\n", pypath); fprintf(stderr, "%s\n", pypath);
@ -443,72 +426,40 @@ KarambaPython::KarambaPython(const ThemeFile& theme, bool reloading):
fprintf(stderr, fprintf(stderr,
"------------------------------------------------------\n"); "------------------------------------------------------\n");
} }
releaseLock(myThreadState);
} }
KarambaPython::~KarambaPython() KarambaPython::~KarambaPython()
{ {
//Clean up Python references //Clean up Python references
if (pythonThemeExtensionLoaded) { if (pythonThemeExtensionLoaded) {
PyThreadState* myThreadState;
getLock(&myThreadState);
//Displose of current python module so we can reload in constructor. //Displose of current python module so we can reload in constructor.
Py_DECREF(pModule); Py_DECREF(pModule);
Py_DECREF(pName); Py_DECREF(pName);
releaseLock(myThreadState);
} }
} }
void KarambaPython::initPython() void KarambaPython::initPython()
{ {
// initialize Python // initialize Python
PyImport_AppendInittab((char*)"karamba", PyInit_karamba);
Py_Initialize(); Py_Initialize();
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION <= 6
// initialize thread support // initialize thread support
PyEval_InitThreads(); PyEval_InitThreads();
#endif
// save a pointer to the main PyThreadState object // save a pointer to the main PyThreadState object
mainThreadState = PyThreadState_Get(); mainThreadState = PyThreadState_Get();
// release the lock
PyEval_ReleaseLock();
} }
void KarambaPython::shutdownPython() void KarambaPython::shutdownPython()
{ {
// shut down the interpreter // shut down the interpreter
PyInterpreterState * mainInterpreterState = mainThreadState->interp; PyThreadState_Swap(mainThreadState);
// create a thread state object for this thread
PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState);
PyThreadState_Swap(myThreadState);
PyEval_AcquireLock();
Py_Finalize(); Py_Finalize();
} }
void KarambaPython::getLock(PyThreadState** myThreadState)
{
// get the global lock
PyEval_AcquireLock();
// create a thread state object for this thread
*myThreadState = PyThreadState_New(mainThreadState->interp);
PyThreadState_Swap(*myThreadState);
}
void KarambaPython::releaseLock(PyThreadState* myThreadState)
{
// swap my thread state out of the interpreter
PyThreadState_Swap(NULL);
// clear out any cruft from thread state object
PyThreadState_Clear(myThreadState);
// delete my thread state object
PyThreadState_Delete(myThreadState);
// release the lock
PyEval_ReleaseLock();
}
PyObject* KarambaPython::getFunc(const char* function) PyObject* KarambaPython::getFunc(const char* function)
{ {
PyObject* pFunc = PyDict_GetItemString(pDict, (char*)function); PyObject* pFunc = PyDict_GetItemString(pDict, (char*)function);
@ -517,17 +468,11 @@ PyObject* KarambaPython::getFunc(const char* function)
return NULL; return NULL;
} }
bool KarambaPython::callObject(const char* func, PyObject* pArgs, bool lock) bool KarambaPython::callObject(const char* func, PyObject* pArgs)
{ {
bool result = false; bool result = false;
PyThreadState* myThreadState;
//tqDebug("Calling %s", func);
if (lock)
getLock(&myThreadState);
PyObject* pFunc = getFunc(func); PyObject* pFunc = getFunc(func);
if (pFunc != NULL) if (pFunc != NULL)
{ {
PyObject* pValue = PyObject_CallObject(pFunc, pArgs); PyObject* pValue = PyObject_CallObject(pFunc, pArgs);
@ -544,8 +489,6 @@ bool KarambaPython::callObject(const char* func, PyObject* pArgs, bool lock)
} }
} }
Py_DECREF(pArgs); Py_DECREF(pArgs);
if (lock)
releaseLock(myThreadState);
return result; return result;
} }
@ -597,8 +540,7 @@ bool KarambaPython::widgetClicked(karamba* k, int x, int y, int button)
return callObject("widgetClicked", pArgs); return callObject("widgetClicked", pArgs);
} }
bool KarambaPython::keyPressed(karamba* k, const Meter* meter, bool KarambaPython::keyPressed(karamba* k, const Meter* meter, const TQString& text)
const TQString& text)
{ {
PyObject* pArgs = Py_BuildValue((char*)"(lls)", k, meter, text.ucs2()); PyObject* pArgs = Py_BuildValue((char*)"(lls)", k, meter, text.ucs2());
return callObject("keyPressed", pArgs); return callObject("keyPressed", pArgs);
@ -660,13 +602,8 @@ bool KarambaPython::itemDropped(karamba* k, TQString text, int x, int y)
bool KarambaPython::themeNotify(karamba* k, const char *from, const char *str) bool KarambaPython::themeNotify(karamba* k, const char *from, const char *str)
{ {
// WARNING WARNING WARNING i had to switch off thread locking to get
// this to work. callNotify is called from INSIDE another locked thread,
// so can never complete because themeNotify will expect locking to be
// released...
//
PyObject* pArgs = Py_BuildValue((char*)"(lss)", k, from, str); PyObject* pArgs = Py_BuildValue((char*)"(lss)", k, from, str);
return callObject("themeNotify", pArgs, false); return callObject("themeNotify", pArgs);
} }
bool KarambaPython::systrayUpdated(karamba* k) bool KarambaPython::systrayUpdated(karamba* k)

@ -45,10 +45,8 @@ protected:
PyObject *pDict; PyObject *pDict;
static PyThreadState* mainThreadState; static PyThreadState* mainThreadState;
void getLock(PyThreadState** myThreadState);
PyObject* getFunc(const char* function); PyObject* getFunc(const char* function);
void releaseLock(PyThreadState* myThreadState); bool callObject(const char* func, PyObject* pArgs);
bool callObject(const char* func, PyObject* pArgs, bool lock=true);
public: public:
KarambaPython(const ThemeFile& theme, bool reloading); KarambaPython(const ThemeFile& theme, bool reloading);

Loading…
Cancel
Save