From 7c7121e92b3ebd2763b4b03227eeec09461d8ea9 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Thu, 5 Feb 2015 22:59:15 +0100 Subject: refactored the initialization and shutdown of extension objects (code is moved from a static method to a real member method), and more importantly: fixed initialization of the PhpCpp::Functor class, previously, we created the class an runtime whenever we needed it, but that turned out to be a cause for crashes when php stopped, this has also been solved --- include/class.h | 6 +-- zend/extensionimpl.cpp | 119 ++++++++++++++++++++++++++++--------------------- zend/extensionimpl.h | 11 ++++- zend/function.cpp | 24 +--------- zend/functor.cpp | 56 +++++++++++++++++++++++ zend/functor.h | 29 ++++++++++++ 6 files changed, 168 insertions(+), 77 deletions(-) create mode 100644 zend/functor.cpp diff --git a/include/class.h b/include/class.h index 45bc236..c7ae32a 100644 --- a/include/class.h +++ b/include/class.h @@ -585,11 +585,11 @@ private: /** * Namespaces and the function have access to the private base class, - * so that the classes can be registered (the function object needs - * this to register the Functor class). + * so that the classes can be registered, and the Functor object needs + * this to register the PhpCpp::Functor class. */ friend class Namespace; - friend class Function; + friend class Functor; /** * All Php::Class also need access to the base class to diff --git a/zend/extensionimpl.cpp b/zend/extensionimpl.cpp index 47b4419..d313498 100644 --- a/zend/extensionimpl.cpp +++ b/zend/extensionimpl.cpp @@ -114,43 +114,8 @@ int ExtensionImpl::processStartup(int type, int module_number TSRMLS_DC) // get the extension auto *extension = find(module_number TSRMLS_CC); - // array contains ini settings - auto *entries = extension->_ini = new zend_ini_entry[extension->_data->iniVariables()+1]; - - // the entry that we're filling - int i=0; - - // Fill the php.ini entries - extension->_data->iniVariables([entries, &i, module_number](Ini &ini) { - - // initialize the function - zend_ini_entry *entry = &entries[i]; - - // fill the property - ini.fill(entry, module_number); - - // move on to the next iteration - i++; - }); - - // last entry should be set to all zero's - memset(&entries[i], 0, sizeof(zend_ini_entry)); - - // register ini entries in Zend core - zend_register_ini_entries(entries, module_number TSRMLS_CC); - // initialize the extension - extension->initialize(module_number TSRMLS_CC); - - // remember that we're initialized (when you use "apache reload" it is - // possible that the processStartup() method is called more than once) - extension->_locked = true; - - // is the callback registered? - if (extension->_onStartup) extension->_onStartup(); - - // done - return BOOL2SUCCESS(true); + return BOOL2SUCCESS(extension->initialize(module_number TSRMLS_CC)); } /** @@ -165,20 +130,8 @@ int ExtensionImpl::processShutdown(int type, int module_number TSRMLS_DC) // get the extension auto *extension = find(module_number TSRMLS_CC); - // unregister the ini entries - zend_unregister_ini_entries(module_number TSRMLS_CC); - - // destruct the ini entries - if (extension->_ini) delete[] extension->_ini; - - // forget the ini entries - extension->_ini = nullptr; - - // is the callback registered? - if (extension->_onShutdown) extension->_onShutdown(); - // done - return BOOL2SUCCESS(true); + return BOOL2SUCCESS(extension->shutdown(module_number TSRMLS_CC)); } /** @@ -381,9 +334,35 @@ zend_module_entry *ExtensionImpl::module() * Initialize the extension after it was started * @param module_number * @param tsrm_ls + * @return bool */ -void ExtensionImpl::initialize(int module_number TSRMLS_DC) +bool ExtensionImpl::initialize(int module_number TSRMLS_DC) { + // array contains ini settings + _ini = new zend_ini_entry[_data->iniVariables()+1]; + + // the entry that we're filling + int i = 0; + + // Fill the php.ini entries + _data->iniVariables([this, &i, module_number](Ini &ini) { + + // initialize the function + zend_ini_entry *entry = &_ini[i]; + + // fill the property + ini.fill(entry, module_number); + + // move on to the next iteration + i++; + }); + + // last entry should be set to all zero's + memset(&_ini[i], 0, sizeof(zend_ini_entry)); + + // register ini entries in Zend core + zend_register_ini_entries(_ini, module_number TSRMLS_CC); + // the constants are registered after the module is ready _data->constants([module_number TSRMLS_CC](const std::string &prefix, Constant &c) { @@ -397,6 +376,46 @@ void ExtensionImpl::initialize(int module_number TSRMLS_DC) // forward to implementation class c.implementation()->initialize(&c, prefix TSRMLS_CC); }); + + // initialize the PhpCpp::Functor class + Functor::initialize(TSRMLS_C); + + // remember that we're initialized (when you use "apache reload" it is + // possible that the processStartup() method is called more than once) + _locked = true; + + // is the callback registered? + if (_onStartup) _onStartup(); + + // done + return true; +} + +/** + * Function that is called when the extension shuts down + * @param module_number + * @param tsrmls + * @return bool + */ +bool ExtensionImpl::shutdown(int module_number TSRMLS_DC) +{ + // unregister the ini entries + zend_unregister_ini_entries(module_number TSRMLS_CC); + + // destruct the ini entries + if (_ini) delete[] _ini; + + // forget the ini entries + _ini = nullptr; + + // shutdown the functor class + Functor::shutdown(TSRMLS_C); + + // is the callback registered? + if (_onShutdown) _onShutdown(); + + // done + return true; } /** diff --git a/zend/extensionimpl.h b/zend/extensionimpl.h index 83deb36..3a0fc63 100644 --- a/zend/extensionimpl.h +++ b/zend/extensionimpl.h @@ -106,8 +106,17 @@ private: * Initialize the namespace after it was registered * @param module_number * @param tsrm_ls + * @return bool + */ + bool initialize(int module_number TSRMLS_DC); + + /** + * Shutdown the extension + * @param module_number + * @param tsrm_ls + * @return bool */ - void initialize(int module_number TSRMLS_DC); + bool shutdown(int module_number TSRMLS_DC); /** * Function that is called when the extension initializes diff --git a/zend/function.cpp b/zend/function.cpp index 01267c0..dddc489 100644 --- a/zend/function.cpp +++ b/zend/function.cpp @@ -17,33 +17,11 @@ */ namespace Php { -/** - * Function returns a pointer to the class-entry of the Functor class - * @return zend_class_entry - */ -zend_class_entry *Function::entry() -{ - // and the actual class entry - static zend_class_entry *entry = nullptr; - - // is the class entry already valid? - if (entry) return entry; - - // construct functor object - static std::unique_ptr functor(new Class("Functor")); - - // we need the TSRMLS variable - TSRMLS_FETCH(); - - // initialize the functor class - return entry = functor->implementation()->initialize(functor.get(), "" TSRMLS_CC); -} - /** * Constructor * @param function The function to be wrapped */ -Function::Function(const std::function &function) : Value(Object(entry(), new Functor(function))) {} +Function::Function(const std::function &function) : Value(Object(Functor::entry(), new Functor(function))) {} /** * End of namespace diff --git a/zend/functor.cpp b/zend/functor.cpp new file mode 100644 index 0000000..7d0404b --- /dev/null +++ b/zend/functor.cpp @@ -0,0 +1,56 @@ +/** + * Functor.cpp + * + * Implementation file for the functor class + * + * @author Emiel Bruijntjes + * @copyright 2015 Copernica BV + */ + +/** + * Dependencies + */ +#include "includes.h" + +/** + * Set up namespace + */ +namespace Php { + +/** + * The classentry + * @var zend_class_entry + */ +zend_class_entry *Functor::_entry = nullptr; + +/** + * Initialize the class + * @param tsrmls + */ +void Functor::initialize(TSRMLS_D) +{ + // leap out if the class entry is already set + if (_entry) return; + + // construct functor object + static std::unique_ptr functor(new Class("PhpCpp::Functor")); + + // initialize the functor class + _entry = functor->implementation()->initialize(functor.get(), "" TSRMLS_CC); +} + +/** + * Shutdown the class + * @param tsrmls + */ +void Functor::shutdown(TSRMLS_D) +{ + // we forget the entry + _entry = nullptr; +} + +/** + * End of namespace + */ +} + diff --git a/zend/functor.h b/zend/functor.h index 7d5bef5..503a05c 100644 --- a/zend/functor.h +++ b/zend/functor.h @@ -46,12 +46,41 @@ public: return _function(params); } + /** + * Get the functor class entry + * @return zend_class_entry + */ + static zend_class_entry *entry() + { + // get the "member" + return _entry; + } + + /** + * Initialize the class + * @param tsrmls + */ + static void initialize(TSRMLS_D); + + /** + * Shutdown the class + * @param tsrmls + */ + static void shutdown(TSRMLS_D); + private: /** * The std::function that is wrapped in PHP code * @var std::function */ const std::function _function; + + /** + * The classentry + * @var zend_class_entry + */ + static zend_class_entry *_entry; + }; /** -- cgit v1.2.3