diff options
Diffstat (limited to 'src')
-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 |
9 files changed, 113 insertions, 117 deletions
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; |