summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/callable.cpp2
-rw-r--r--src/classimpl.cpp33
-rw-r--r--src/exception.cpp34
-rw-r--r--src/extensionimpl.cpp4
-rw-r--r--src/extensionimpl.h2
-rw-r--r--src/includes.h6
-rw-r--r--src/origexception.cpp35
-rw-r--r--src/origexception.h112
-rw-r--r--src/value.cpp2
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;