summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-12-30 06:06:51 -0800
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2013-12-30 06:06:51 -0800
commit678fb09044c87a2f4bf843bb55eb4b057f1c131a (patch)
tree31d23b285b4215a1a563b6338e2ac086e07f6736 /src
parent00be9c5573d6858c89e2f305b4504b0a477ff230 (diff)
exceptions thrown in PHP code can now be caugth and processed by C++ code
Diffstat (limited to 'src')
-rw-r--r--src/function.cpp7
-rw-r--r--src/includes.h1
-rw-r--r--src/origexception.cpp80
-rw-r--r--src/value.cpp11
4 files changed, 95 insertions, 4 deletions
diff --git a/src/function.cpp b/src/function.cpp
index cc4315f..3269448 100644
--- a/src/function.cpp
+++ b/src/function.cpp
@@ -43,6 +43,13 @@ void invoke_function(INTERNAL_FUNCTION_PARAMETERS)
// get the result
result = function->invoke(params);
}
+ catch (Php::OrigException &exception)
+ {
+ // we caught an exception that was original thrown by PHP code, and not
+ // processed by C++ code, this means that we're going to restore this
+ // exception so that it can be further handled by PHP
+ exception.restore();
+ }
catch (Php::Exception &exception)
{
// an exception originally thrown by C++ should be passed on to PHP
diff --git a/src/includes.h b/src/includes.h
index 18e9951..933e317 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -58,6 +58,7 @@
#include "../include/classinfo.h"
#include "../include/extension.h"
#include "../include/exception.h"
+#include "../include/origexception.h"
#include "../include/init.h"
/**
diff --git a/src/origexception.cpp b/src/origexception.cpp
new file mode 100644
index 0000000..299730e
--- /dev/null
+++ b/src/origexception.cpp
@@ -0,0 +1,80 @@
+/**
+ * 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 {
+
+/**
+ * Constructor
+ * @param zval
+ */
+OrigException::OrigException(struct _zval_struct *zval) :
+ Value(zval),
+ Exception("OrigException"),
+ _restored(false)
+{
+ std::cout << "save the exception" << std::endl;
+
+ // save the exception
+ zend_exception_save();
+}
+
+/**
+ * Copy constructor
+ * @param exception
+ */
+OrigException::OrigException(const OrigException &exception) :
+ Value(exception),
+ Exception("OrigException"),
+ _restored(exception._restored) {}
+
+/**
+ * Move constructor
+ * @param exception
+ */
+OrigException::OrigException(OrigException &&exception) :
+ Value(std::move(exception)),
+ Exception("OrigException"),
+ _restored(exception._restored) {}
+
+/**
+ * Destructor
+ */
+OrigException::~OrigException()
+{
+ // skip if the exception was restored
+ if (_restored) return;
+
+ // clean up the exception
+ zend_clear_exception();
+}
+
+/**
+ * Restore the exception
+ * @internal
+ */
+void OrigException::restore()
+{
+ std::cout << "restore the exception" << std::endl;
+
+ // restore the exception
+ zend_exception_restore();
+
+ // mark exception as restored
+ _restored = true;
+}
+
+/**
+ * End of namespace
+ */
+}
+
diff --git a/src/value.cpp b/src/value.cpp
index 194934d..49c9c2b 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -868,14 +868,17 @@ Value Value::exec(int argc, zval ***params)
// the return zval
zval *retval = nullptr;
+ // the current exception
+ zval *oldException = EG(exception);
+
// call the function
if (call_user_function_ex(CG(function_table), NULL, _val, &retval, argc, params, 1, NULL) != SUCCESS) return nullptr;
- // was a value returned?
- if (retval) return Value(retval);
+ // was an exception thrown?
+ if (oldException != EG(exception)) throw OrigException(EG(exception));
- // no value was returned, return NULL
- return nullptr;
+ // no (additional) exception was thrown
+ return retval ? Value(retval) : nullptr;
}
/**