diff options
-rw-r--r-- | Makefile | 20 | ||||
-rw-r--r-- | config/config.cpp | 28 | ||||
-rw-r--r-- | include/exception.h | 37 | ||||
-rw-r--r-- | phpcpp.h | 26 | ||||
-rw-r--r-- | src/callable.cpp | 2 | ||||
-rw-r--r-- | src/classimpl.cpp | 33 | ||||
-rw-r--r-- | src/exception.cpp | 34 | ||||
-rw-r--r-- | src/extensionimpl.cpp | 4 | ||||
-rw-r--r-- | src/extensionimpl.h | 2 | ||||
-rw-r--r-- | src/includes.h | 6 | ||||
-rw-r--r-- | src/origexception.cpp | 35 | ||||
-rw-r--r-- | src/origexception.h | 112 | ||||
-rw-r--r-- | src/value.cpp | 2 |
13 files changed, 138 insertions, 203 deletions
@@ -140,24 +140,13 @@ OBJECTS = $(SOURCES:%.cpp=%.o) PHP_OBJECTS = $(PHP_SOURCES:%.cpp=%.o) HHVM_OBJECTS = $(HHVM_SOURCES:%.cpp=%.o) -# -# Configuration program -# -# During installation, a configuration utility will be installed. It is -# compiled with the following instructions -# - -CONFIG_UTILITY = ./create_config -CONFIG_SOURCES = $(wildcard config/*.cpp) -CONFIG_FLAGS = `php-config --includes` -o - # # End of the variables section. Here starts the list of instructions and # dependencies that are used by the compiler. # -all: ${PHP_LIBRARY} ${CONFIG_UTILITY} +all: ${PHP_LIBRARY} ${PHP_LIBRARY}: ${OBJECTS} ${PHP_OBJECTS} ${LINKER} ${PHP_LINKER_FLAGS} -o $@ ${OBJECTS} ${PHP_OBJECTS} @@ -165,11 +154,8 @@ ${PHP_LIBRARY}: ${OBJECTS} ${PHP_OBJECTS} ${HHVM_LIBRARY}: ${OBJECTS} ${HHVM_OBJECTS} ${LINKER} ${HHVM_LINKER_FLAGS} -o $@ ${OBJECTS} ${HHVM_OBJECTS} -${CONFIG_UTILITY}: - ${COMPILER} ${CONFIG_FLAGS} $@ ${CONFIG_SOURCES} - clean: - ${RM} ${OBJECTS} ${PHP_OBJECTS} ${HHVM_OBJECTS} ${PHP_LIBRARY} ${HHVM_LIBRARY} ${CONFIG_UTILITY} + ${RM} ${OBJECTS} ${PHP_OBJECTS} ${HHVM_OBJECTS} ${PHP_LIBRARY} ${HHVM_LIBRARY} ${OBJECTS}: ${COMPILER} ${PHP_COMPILER_FLAGS} -o $@ ${@:%.o=%.cpp} @@ -186,10 +172,8 @@ install: ${CP} include/*.h ${INSTALL_HEADERS}/phpcpp if [ -e ${PHP_LIBRARY} ]; then ${CP} ${PHP_LIBRARY} ${INSTALL_LIB}; fi if [ -e ${HHVM_LIBRARY} ]; then ${CP} ${HHVM_LIBRARY} ${INSTALL_LIB}; fi - ${CONFIG_UTILITY} > ${INSTALL_HEADERS}/phpcpp/config.h test: mkdir -p ./tests/include/zts/phpcpp - ${CONFIG_UTILITY} > ./tests/include/zts/phpcpp/config.h cd tests && ./test.sh -p "${PHP_BIN}" diff --git a/config/config.cpp b/config/config.cpp deleted file mode 100644 index 2fcd5ad..0000000 --- a/config/config.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Config.cpp - * - * Simple programs that creates the config file for PHP-CPP. PHP-CPP needs - * a different config file when it is installed on a system with multi-threaded - * PHP, and on a system with single threaded PHP. - * - * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2014 Copernica BV - */ -#include <iostream> -#include <php_config.h> - -/** - * Main procedure - * @return int - */ -int main() -{ -#ifdef ZTS - // also define ZTS in the config file - std::cout << "#define ZTS" << std::endl; -#endif - - // done - return 0; -} - diff --git a/include/exception.h b/include/exception.h index dd38035..671df9e 100644 --- a/include/exception.h +++ b/include/exception.h @@ -30,42 +30,51 @@ private: */ int _code; + /** + * Has this exception been processed by native C++ code? + * @var bool + */ + bool _processed = false; + public: /** * Constructor * @param &string */ - Exception(const std::string &message, int code = 0) : std::exception(), _message(message), _code(code) - { - } + Exception(const std::string &message, int code = 0) : std::exception(), _message(message), _code(code) {} /** * Destructor */ - virtual ~Exception() throw() + virtual ~Exception() throw() {} + + /** + * Overridden what method + * @return const char * + */ + virtual const char *what() const noexcept override { + return _message.c_str(); } /** * Returns the message of the exception. * @return &string */ - std::string &message() throw() + const std::string &message() const throw() { return _message; } /** - * Process the exception - * - * This method is called only from within the PHP-CPP library, - * and will turn the exception into a PHP exception - * - * @param tsrm_ls - * - * @internal + * Is this a native exception (one that was thrown from C++ code) + * @return bool */ - virtual void process(TSRMLS_D); + virtual bool native() const + { + // yes, it is native + return true; + } }; /** @@ -23,32 +23,6 @@ #include <map> /** - * Include PHP config - */ -#include <phpcpp/config.h> - -/** - * Is ZTS enabled? - */ -#ifdef ZTS - - // enable TSRM -# define TSRMLS_C tsrm_ls -# define TSRMLS_CC ,tsrm_ls -# define TSRMLS_D void ***tsrm_ls -# define TSRMLS_DC ,void ***tsrm_ls - -#else - - // disable TSRM -# define TSRMLS_C -# define TSRMLS_CC -# define TSRMLS_D -# define TSRMLS_DC - -#endif - -/** * Include all headers files that are related to this library */ #include <phpcpp/exception.h> diff --git a/src/callable.cpp b/src/callable.cpp index d1b94c5..737b85b 100644 --- a/src/callable.cpp +++ b/src/callable.cpp @@ -46,7 +46,7 @@ static void invoke_callable(INTERNAL_FUNCTION_PARAMETERS) catch (Exception &exception) { // process the exception - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } diff --git a/src/classimpl.cpp b/src/classimpl.cpp index 8e062d4..d63956a 100644 --- a/src/classimpl.cpp +++ b/src/classimpl.cpp @@ -114,7 +114,7 @@ void ClassImpl::callMethod(INTERNAL_FUNCTION_PARAMETERS) catch (Exception &exception) { // process the exception - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } @@ -155,12 +155,11 @@ void ClassImpl::callInvoke(INTERNAL_FUNCTION_PARAMETERS) { // because of the two-step nature, we are going to report the error ourselves zend_error(E_ERROR, "Function name must be a string"); - } catch (Exception &exception) { // process the exception - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } @@ -419,7 +418,7 @@ int ClassImpl::compare(zval *val1, zval *val2 TSRMLS_DC) { // a Php::Exception was thrown by the extension __compare function, // pass this on to user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // what shall we return here... return 1; @@ -492,7 +491,7 @@ int ClassImpl::cast(zval *val, zval *retval, int type TSRMLS_DC) catch (Exception &exception) { // pass on the exception to php userspace - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // done return FAILURE; @@ -577,7 +576,7 @@ int ClassImpl::countElements(zval *object, long *count TSRMLS_DC) catch (Exception &exception) { // process the exception - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // unreachable return FAILURE; @@ -640,7 +639,7 @@ zval *ClassImpl::readDimension(zval *object, zval *offset, int type TSRMLS_DC) catch (Exception &exception) { // process the exception (send it to user space) - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // unreachable return Value(nullptr).detach(); @@ -685,7 +684,7 @@ void ClassImpl::writeDimension(zval *object, zval *offset, zval *value TSRMLS_DC catch (Exception &exception) { // process the exception (send it to user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } else @@ -734,7 +733,7 @@ int ClassImpl::hasDimension(zval *object, zval *member, int check_empty TSRMLS_D catch (Exception &exception) { // process the exception (send it to user space) - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // unreachable return false; @@ -777,7 +776,7 @@ void ClassImpl::unsetDimension(zval *object, zval *member TSRMLS_DC) catch (Exception &exception) { // process the exception (send it to user space) - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } else @@ -894,7 +893,7 @@ zval *ClassImpl::readProperty(zval *object, zval *name, int type, const zend_lit { // user threw an exception in its magic method // implementation, send it to user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // unreachable return Value(nullptr).detach(); @@ -971,7 +970,7 @@ void ClassImpl::writeProperty(zval *object, zval *name, zval *value, const zend_ { // user threw an exception in its magic method // implementation, send it to user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } @@ -1052,7 +1051,7 @@ int ClassImpl::hasProperty(zval *object, zval *name, int has_set_exists, const z { // user threw an exception in its magic method // implementation, send it to user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // unreachable return false; @@ -1113,7 +1112,7 @@ void ClassImpl::unsetProperty(zval *object, zval *member, const zend_literal *ke { // user threw an exception in its magic method // implementation, send it to user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } @@ -1147,7 +1146,7 @@ void ClassImpl::destructObject(zend_object *object, zend_object_handle handle TS { // a regular Php::Exception was thrown by the extension, pass it on // to PHP user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); } } @@ -1162,7 +1161,7 @@ void ClassImpl::freeObject(zend_object *object TSRMLS_DC) ObjectImpl *obj = ObjectImpl::find(object); // no longer need it - obj->destruct(TSRMLS_CC); + obj->destruct(TSRMLS_C); } /** @@ -1228,7 +1227,7 @@ zend_object_iterator *ClassImpl::getIterator(zend_class_entry *entry, zval *obje { // user threw an exception in its method // implementation, send it to user space - exception.process(TSRMLS_C); + process(exception TSRMLS_CC); // unreachable return nullptr; diff --git a/src/exception.cpp b/src/exception.cpp deleted file mode 100644 index 810a73c..0000000 --- a/src/exception.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Exception.cpp - * - * Implementation for the exception class - * - * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2014 Copernica BV - */ -#include "includes.h" - -/** - * Set up namespace - */ -namespace Php { - -/** - * Process the exception - * - * This method is called only from within the PHP-CPP library, - * and will turn the exception into a PHP exception - * - * @param tsrm_ls - */ -void Exception::process(TSRMLS_D) -{ - // an exception originally thrown by C++ should be passed on to PHP - zend_throw_exception(zend_exception_get_default(TSRMLS_C), (char*)message().c_str(), 0 TSRMLS_CC); -} - -/** - * End namespace - */ -} - diff --git a/src/extensionimpl.cpp b/src/extensionimpl.cpp index 0197757..9562362 100644 --- a/src/extensionimpl.cpp +++ b/src/extensionimpl.cpp @@ -115,7 +115,7 @@ int ExtensionImpl::onStartup(int type, int module_number TSRMLS_DC) auto *extension = find(module_number TSRMLS_CC); // initialize the extension - extension->initialize(TSRMLS_CC); + extension->initialize(TSRMLS_C); // is the callback registered? if (extension->_onStartup) extension->_onStartup(); @@ -289,7 +289,7 @@ void ExtensionImpl::initialize(TSRMLS_D) _data->apply([TSRMLS_C](const std::string &prefix, ClassBase &c) { // forward to implementation class - c.implementation()->initialize(&c, prefix TSRMLS_C); + c.implementation()->initialize(&c, prefix TSRMLS_CC); }); } diff --git a/src/extensionimpl.h b/src/extensionimpl.h index 8c9ae58..cc37354 100644 --- a/src/extensionimpl.h +++ b/src/extensionimpl.h @@ -166,7 +166,7 @@ private: * Initialize the namespace after it was registered * @param tsrm_ls */ - void initialize(TSRMLS_DC); + void initialize(TSRMLS_D); /** * Function that is called when the extension initializes diff --git a/src/includes.h b/src/includes.h index f547eb2..0019244 100644 --- a/src/includes.h +++ b/src/includes.h @@ -23,9 +23,9 @@ // for debug #include <iostream> -//#define ZTS -//#define THREAD_T pthread_t -//#define MUTEX_T pthread_mutex_t * +#define ZTS +#define THREAD_T pthread_t +#define MUTEX_T pthread_mutex_t * /** * PHP includes diff --git a/src/origexception.cpp b/src/origexception.cpp deleted file mode 100644 index f64d696..0000000 --- a/src/origexception.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Implementation of the exception that was originally thrown by PHP - * code or the zend engine, and that could or could not be picked - * up by C++ code - * - * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2013 Copernica BV - */ -#include "includes.h" - -/** - * Set up namespace - */ -namespace Php { - -/** - * Destructor - */ -OrigException::~OrigException() noexcept -{ - // skip if the exception was restored - if (_restored) return; - - // we need the tsrm_ls var - TSRMLS_FETCH(); - - // clean up the exception, because it was handled in C++ code - zend_clear_exception(TSRMLS_C); -} - -/** - * End of namespace - */ -} - diff --git a/src/origexception.h b/src/origexception.h index 5cbb0e1..775e412 100644 --- a/src/origexception.h +++ b/src/origexception.h @@ -18,62 +18,128 @@ namespace Php { */ class OrigException : public Value, public Exception { -private: +private: /** - * Has the exception been restored by the C++ code so that it can be dealt by PHP? - * @var boolean + * Is this a an exception that was caught by extension C++ code. + * + * When the object is initially created, we assume that it will be caught + * by C++ code. If it later turns out that the PHP-CPP can catch this + * exception after the extension C++ code ran, the variable is set back + * to false. + * + * @var bool + */ + bool _handled = true; + +#ifdef ZTS + /** + * When we run in multi-thread mode, we store the thread handle + * @var void*** */ - bool _restored = false; + TSRMLS_D; +#endif public: /** * Constructor - * @param zval + * @param val */ - OrigException(struct _zval_struct *zval) : - Value(zval), Exception("OrigException") {} + OrigException(zval *val TSRMLS_DC) : + Value(val), Exception("OrigException") + { +#ifdef ZTS + // copy tsrm_ls + this->TSRMLS_C = TSRMLS_C; +#endif + } /** * Copy constructor * @param exception */ OrigException(const OrigException &exception) : - Value(exception), Exception("OrigException"), _restored(exception._restored) {} + Value(exception), Exception("OrigException"), _handled(exception._handled) + { +#ifdef ZTS + // copy tsrm_ls + TSRMLS_C = exception.TSRMLS_C; +#endif + } /** * Move constructor * @param exception */ OrigException(OrigException &&exception) : - Value(std::move(exception)), Exception("OrigException"), _restored(exception._restored) + Value(std::move(exception)), Exception("OrigException"), _handled(exception._handled) { - // set other exception to restored so that it wont - // do anything on destruction - exception._restored = true; + // set other exception to handled so that it wont do anything on destruction + exception._handled = true; + +#ifdef ZTS + // copy tsrm_ls + TSRMLS_C = exception.TSRMLS_C; +#endif } /** * Destructor */ - virtual ~OrigException() throw(); + virtual ~OrigException() throw() + { + // if the exception was not handled by C++ code, we're not going to do anything + // and the exception stays active + if (!_handled) return; + + // the exception was handled, so we should clean it up + zend_clear_exception(TSRMLS_C); + } /** - * Process the exception - * - * This will restore the exception so that it can be further processed - * in PHP code - * - * @param tsrm_ls - * @internal + * This is _not_ a native exception, it was thrown by a PHP script + * @return bool */ - virtual void process(TSRMLS_D) override + virtual bool native() const override { - // mark exception as restored - _restored = true; + return false; + } + + /** + * Reactivate the exception + */ + void reactivate() + { + // it was not handled by extension C++ code + _handled = false; } }; /** + * Global function to process an exception + * @param exception + * @param tsrm_ls + */ +inline void process(Exception &exception TSRMLS_DC) +{ + // is this a native exception? + if (exception.native()) + { + // the exception is native, call the zend throw method + zend_throw_exception(zend_exception_get_default(TSRMLS_C), (char *)exception.what(), 0 TSRMLS_CC); + } + else + { + // this is not a native exception, so it was originally thrown by a + // php script, and then not caught by the c++ of the extensiont, we are + // going to tell to the exception that it is still active + OrigException &orig = static_cast<OrigException&>(exception); + + // reactive the exception + orig.reactivate(); + } +} + +/** * End of namespace */ } diff --git a/src/value.cpp b/src/value.cpp index 9addb8c..2ca1585 100644 --- a/src/value.cpp +++ b/src/value.cpp @@ -1257,7 +1257,7 @@ static Value do_exec(zval **object, zval *method, int argc, zval ***params) { // was an exception thrown inside the function? In that case we throw a C++ new exception // to give the C++ code the chance to catch it - if (oldException != EG(exception) && EG(exception)) throw OrigException(EG(exception)); + if (oldException != EG(exception) && EG(exception)) throw OrigException(EG(exception) TSRMLS_CC); // no (additional) exception was thrown return retval ? Value(retval) : nullptr; |