diff options
Diffstat (limited to 'src/origexception.h')
-rw-r--r-- | src/origexception.h | 112 |
1 files changed, 89 insertions, 23 deletions
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 */ } |