|
Boost : |
From: Norman Shelley (rrdn60) (rrdn60_at_[hidden])
Date: 2001-05-18 13:14:54
Throwing an error within a class init causes a segment fault.
Boost1.21.1
[524] % uname -a
HP-UX wvenus B.10.20 A 9000/782 2009382447 two-user license
[525] % gcc --version
2.95.3
[526] % gmake abc_sl.sl
g++ - -I/usr/local/include/python2.1 -ftemplate-depth-21 -fpic -g -c
abc_sl.cpp
g++ -o abc_sl.sl abc_sl.o -shared -fpic -lboost_python -ldld -lm
% python2.1
Python 2.1 (#2, Apr 24 2001, 11:33:06)
[GCC 2.95.3 20010315 (release)] on hp-uxB
Type "copyright", "credits" or "license" for more information.
>>> from mot_ddl_wssg import abc_sl
>>> abc_sl.command("test")
command: raise_error: 'Command problem!!'
>>>Command problem!!<<<
Traceback (most recent call last):
File "<stdin>", line 1, in ?
abc.error: Command problem!!
>>> abc_sl.Listing(2)
Listing creation NULL: raise_error: 'A problem!!'
>>>A problem!!<<<
Segmentation fault
#include <cstddef>
#include <string>
#include <cstring>
#include <iostream>
#include <sstream>
#include <typeinfo>
#include <exception>
#include <boost/python/reference.hpp>
#include <boost/python/module_builder.hpp>
#include <boost/python/class_builder.hpp>
#include <assert.h>
// Needed for Py_None
#include <python2.1/object.h>
// Needed for PyFile_AsFile
#include <python2.1/fileobject.h>
#define BPC BOOST_PYTHON_CONVERSION
namespace python = boost::python;
namespace { // Avoid cluttering the global namespace.
PyObject *abcError; // Initialized in BOOST_PYTHON_MODULE_INIT(abc_sl)
void raise_error(const string& errstr) {
cerr << "raise_error: '" << errstr << "'\n";
PyErr_SetString(abcError, errstr.c_str());
fprintf(stderr, ">>>%s<<<\n", errstr.c_str());
throw python::error_already_set();
}
void command(const std::string& cmd) {
cerr << "command: ";
raise_error("Command problem!!");
}
class Listing {
//CAVEAT: Internal FILE* is held and closed only on instance deletion
public:
Listing(int type) {
cerr << "Listing creation NULL: ";
raise_error("A problem!!");
__fp = tmpfile();
cerr << "fp " << __fp << "\n";
listing(type);
}
Listing(int type, const std::string& filename) {
cerr << "Listing creation " << filename << ": ";
__fp = fopen(filename.c_str(), "w+");
cerr << "fp " << __fp << "\n";
listing(type);
}
~Listing() {
//fprintf(stderr, "Listing destruction: fp %x\n", __fp);
fclose(__fp);
}
int fileno() {
if (__fp == NULL) {
raise_error("NULL file pointer");
}
//The std:: prefix is necessary for it to compile
return std::fileno(__fp);
}
private:
FILE *__fp;
void listing(int type) {
if (0) {
fclose(__fp);
__fp = NULL;
}
}
};
}
// Python requires an exported function called init<module-name> in
every
// extension module. This is where we build the module contents.
BOOST_PYTHON_MODULE_INIT(abc_sl)
{
try
{
// Create an object representing this extension module
python::module_builder abc_sl_module("abc_sl");
// Create a Python abc exception type/class
abcError = PyErr_NewException("abc.error", NULL, NULL);
if (abcError == NULL) {
throw python::error_already_set();
}
//PyObject *d = PyModule_GetDict(abc_sl_module.module());
//PyDict_SetItemString(d, "error", abcError);
// Place abcError in the abc_sl_module namespace as "error"
abc_sl_module.add(python::make_ref(abcError), "error");
abc_sl_module.def(command, "command");
python::class_builder<Listing> ListingClass(abc_sl_module,
"Listing");
// Add in __init__ functions (constructors)
ListingClass.def(python::constructor<int>());
ListingClass.def(python::constructor<int,const std::string>());
// Add in regular member functions
ListingClass.def(&Listing::fileno, "fileno");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}
#include <cstddef>
#include <string>
#include <cstring>
#include <iostream>
#include <sstream>
#include <typeinfo>
#include <exception>
#include <boost/python/reference.hpp>
#include <boost/python/module_builder.hpp>
#include <boost/python/class_builder.hpp>
#include <assert.h>
// Needed for Py_None
#include <python2.1/object.h>
// Needed for PyFile_AsFile
#include <python2.1/fileobject.h>
#define BPC BOOST_PYTHON_CONVERSION
namespace python = boost::python;
namespace { // Avoid cluttering the global namespace.
PyObject *abcError; // Initialized in BOOST_PYTHON_MODULE_INIT(abc_sl)
void raise_error(const string& errstr) {
cerr << "raise_error: '" << errstr << "'\n";
PyErr_SetString(abcError, errstr.c_str());
fprintf(stderr, ">>>%s<<<\n", errstr.c_str());
throw python::error_already_set();
}
void command(const std::string& cmd) {
cerr << "command: ";
raise_error("Command problem!!");
}
class Listing {
//CAVEAT: Internal FILE* is held and closed only on instance deletion
public:
Listing(int type) {
cerr << "Listing creation NULL: ";
raise_error("A problem!!");
__fp = tmpfile();
cerr << "fp " << __fp << "\n";
listing(type);
}
Listing(int type, const std::string& filename) {
cerr << "Listing creation " << filename << ": ";
__fp = fopen(filename.c_str(), "w+");
cerr << "fp " << __fp << "\n";
listing(type);
}
~Listing() {
//fprintf(stderr, "Listing destruction: fp %x\n", __fp);
fclose(__fp);
}
int fileno() {
if (__fp == NULL) {
raise_error("NULL file pointer");
}
//The std:: prefix is necessary for it to compile
return std::fileno(__fp);
}
private:
FILE *__fp;
void listing(int type) {
if (0) {
fclose(__fp);
__fp = NULL;
}
}
};
}
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
BOOST_PYTHON_MODULE_INIT(abc_sl)
{
try
{
// Create an object representing this extension module
python::module_builder abc_sl_module("abc_sl");
// Create a Python abc exception type/class
abcError = PyErr_NewException("abc.error", NULL, NULL);
if (abcError == NULL) {
throw python::error_already_set();
}
//PyObject *d = PyModule_GetDict(abc_sl_module.module());
//PyDict_SetItemString(d, "error", abcError);
// Place abcError in the abc_sl_module namespace as "error"
abc_sl_module.add(python::make_ref(abcError), "error");
abc_sl_module.def(command, "command");
python::class_builder<Listing> ListingClass(abc_sl_module,
"Listing");
// Add in __init__ functions (constructors)
ListingClass.def(python::constructor<int>());
ListingClass.def(python::constructor<int,const std::string>());
// Add in regular member functions
ListingClass.def(&Listing::fileno, "fileno");
}
catch(...)
{
python::handle_exception(); // Deal with the exception for Python
}
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk