Fix various issues:

+ fix dangling pointers when fetching Python error text
+ initialize members in overloaded constructors of Exception class
+ implement assignment operator in sub-class
+ move to PyCXX API to simplify handling with reference counting and reading values from the dict
This commit is contained in:
wmayer
2017-05-15 18:49:09 +02:00
parent 38e313f0e0
commit 1d8206acbf
5 changed files with 65 additions and 58 deletions

View File

@@ -29,6 +29,7 @@
#include "Exception.h"
#include "Console.h"
#include <CXX/Objects.hxx>
using namespace Base;
@@ -37,30 +38,34 @@ TYPESYSTEM_SOURCE(Base::Exception,Base::BaseClass);
Exception::Exception(void)
: _line(0)
{
_sErrMsg = "FreeCAD Exception";
}
Exception::Exception(const Exception &inst)
: BaseClass(),_sErrMsg(inst._sErrMsg), _file(inst._file), _line(inst._line), _function(inst._function)
: _sErrMsg(inst._sErrMsg), _file(inst._file),
_line(inst._line), _function(inst._function)
{
}
Exception::Exception(const char * sMessage)
: _sErrMsg(sMessage)
: _sErrMsg(sMessage), _line(0)
{
}
Exception::Exception(const std::string& sMessage)
: _sErrMsg(sMessage)
: _sErrMsg(sMessage), _line(0)
{
}
Exception &Exception::operator=(const Exception &inst)
{
_sErrMsg = inst._sErrMsg;
return *this;
_sErrMsg = inst._sErrMsg;
_file = inst._file;
_line = inst._line;
_function = inst._function;
return *this;
}
const char* Exception::what(void) const throw()
@@ -100,38 +105,31 @@ void Exception::ReportException (void) const
PyObject * Exception::getPyObject(void)
{
PyObject *edict = PyDict_New();
PyDict_SetItemString(edict, "sclassname", PyString_FromString(typeid(*this).name()));
PyDict_SetItemString(edict, "sErrMsg", PyString_FromString(this->getMessage().c_str()));
PyDict_SetItemString(edict, "sfile", PyString_FromString(this->getFile().c_str()));
PyDict_SetItemString(edict, "iline", PyInt_FromLong(this->getLine()));
PyDict_SetItemString(edict, "sfunction", PyString_FromString(this->getFunction().c_str()));
PyDict_SetItemString(edict, "swhat", PyString_FromString(this->what()));
return edict;
Py::Dict edict;
edict.setItem("sclassname", Py::String(typeid(*this).name()));
edict.setItem("sErrMsg", Py::String(this->getMessage()));
edict.setItem("sfile", Py::String(this->getFile()));
edict.setItem("iline", Py::Long(this->getLine()));
edict.setItem("sfunction", Py::String(this->getFunction()));
edict.setItem("swhat", Py::String(this->what()));
return Py::new_reference_to(edict);
}
void Exception::setPyObject( PyObject * pydict)
{
if(pydict!=NULL) {
PyObject *pystring;
if (pydict!=NULL) {
Py::Dict edict(pydict);
if (edict.hasKey("sfile"))
_file = static_cast<std::string>(Py::String(edict.getItem("sfile")));
pystring = PyDict_GetItemString(pydict,"sfile");
if(pystring!=NULL)
_file = std::string(PyString_AsString(pystring));
if (edict.hasKey("sfunction"))
_function = static_cast<std::string>(Py::String(edict.getItem("sfunction")));
pystring = PyDict_GetItemString(pydict,"sfunction");
if(pystring!=NULL)
_function = std::string(PyString_AsString(pystring));
if (edict.hasKey("sErrMsg"))
_sErrMsg = static_cast<std::string>(Py::String(edict.getItem("sErrMsg")));
pystring = PyDict_GetItemString(pydict,"sErrMsg");
if(pystring!=NULL)
_sErrMsg = std::string(PyString_AsString(pystring));
pystring = PyDict_GetItemString(pydict,"iline");
if(pystring!=NULL)
_line = PyInt_AsLong(pystring);
if (edict.hasKey("iline"))
_line = static_cast<int>(Py::Long(edict.getItem("iline")));
}
}
@@ -244,6 +242,14 @@ std::string FileException::getFileName() const
return file.fileName();
}
FileException & FileException::operator=(const FileException &inst)
{
Exception::operator = (inst);
file = inst.file;
_sErrMsgAndFileName = inst._sErrMsgAndFileName;
return *this;
}
const char* FileException::what() const throw()
{
return _sErrMsgAndFileName.c_str();
@@ -281,20 +287,19 @@ void FileException::ReportException (void) const
PyObject * FileException::getPyObject(void)
{
PyObject *edict = Exception::getPyObject();
PyDict_SetItemString(edict, "filename", PyString_FromString(this->file.fileName().c_str()));
return edict;
Py::Dict edict(Exception::getPyObject(), true);
edict.setItem("filename", Py::String(this->file.fileName()));
return Py::new_reference_to(edict);
}
void FileException::setPyObject( PyObject * pydict)
{
if(pydict!=NULL) {
if (pydict!=NULL) {
Exception::setPyObject(pydict);
PyObject *pystring = PyDict_GetItemString(pydict,"filename");
if(pystring!=NULL)
file = FileInfo(PyString_AsString(pystring));
Py::Dict edict(pydict);
if (edict.hasKey("filename"))
file.setFile(static_cast<std::string>(Py::String(edict.getItem("filename"))));
}
}

View File

@@ -186,6 +186,8 @@ public:
FileException(const FileException &inst);
/// Destruction
virtual ~FileException() throw() {}
/// Assignment operator
FileException &operator=(const FileException &inst);
/// Description of the exception
virtual const char* what() const throw();
/// Report generation

View File

@@ -23,6 +23,7 @@
#include "PreCompiled.h"
#include "ExceptionFactory.h"
#include <CXX/Objects.hxx>
using namespace Base;
@@ -46,12 +47,9 @@ void ExceptionFactory::raiseException (PyObject * pydict) const
{
std::string classname;
PyObject *pystring;
pystring = PyDict_GetItemString(pydict,"sclassname");
if(pystring!=NULL) {
classname = std::string(PyString_AsString(pystring));
Py::Dict edict(pydict);
if (edict.hasKey("sclassname")) {
classname = static_cast<std::string>(Py::String(edict.getItem("sclassname")));
std::map<const std::string, AbstractProducer*>::const_iterator pProd;

View File

@@ -87,22 +87,21 @@ PyException::~PyException() throw()
void PyException::ThrowException(void)
{
PyException myexcp = PyException();
if(PP_PyDict_Object!=NULL) {
PyObject *pystring;
PyGILStateLocker locker;
if (PP_PyDict_Object!=NULL) {
// delete the Python dict upon destruction of edict
Py::Dict edict(PP_PyDict_Object, true);
PP_PyDict_Object = 0;
pystring = PyDict_GetItemString(PP_PyDict_Object,"sclassname");
if(pystring==NULL)
if (!edict.hasKey("sclassname"))
throw myexcp;
std::string exceptionname = std::string(PyString_AsString(pystring));
if(!Base::ExceptionFactory::Instance().CanProduce(exceptionname.c_str()))
std::string exceptionname = static_cast<std::string>(Py::String(edict.getItem("sclassname")));
if (!Base::ExceptionFactory::Instance().CanProduce(exceptionname.c_str()))
throw myexcp;
Base::ExceptionFactory::Instance().raiseException(PP_PyDict_Object);
Base::ExceptionFactory::Instance().raiseException(edict.ptr());
}
else
throw myexcp;

View File

@@ -259,14 +259,17 @@ void PP_Fetch_Error_Text()
if (errdata != NULL &&
(PyDict_Check(errdata)) ) /* str() increfs */
{
pystring = PyDict_GetItemString(errdata,"swhat");
// PyDict_GetItemString returns a borrowed reference
// so we must make sure not to decrement the reference
PyObject* value = PyDict_GetItemString(errdata,"swhat");
if(pystring!=NULL) {
strncpy(PP_last_error_info, PyString_AsString(pystring), MAX);
if (value!=NULL) {
strncpy(PP_last_error_info, PyString_AsString(value), MAX);
PP_last_error_info[MAX-1] = '\0';
}
pydict = errdata;
Py_INCREF(pydict);
}
else if (errdata != NULL &&
(pystring = PyObject_Str(errdata)) != NULL && /* str(): increfs */