From 5235f87126cc2bca3907daada9f59e0c7c7bc834 Mon Sep 17 00:00:00 2001 From: Emiel Bruijntjes Date: Tue, 20 Jan 2015 13:45:17 +0100 Subject: PHP-CPP now checks whether an already compiled extension is still compatible with the PHP-CPP library. This prevents weird crashes when users update their PHP-CPP library, without recompiling their extensions --- zend/extensionimpl.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) (limited to 'zend/extensionimpl.cpp') diff --git a/zend/extensionimpl.cpp b/zend/extensionimpl.cpp index 262ecdb..fd97a76 100644 --- a/zend/extensionimpl.cpp +++ b/zend/extensionimpl.cpp @@ -219,13 +219,35 @@ int ExtensionImpl::processIdle(int type, int module_number TSRMLS_DC) return BOOL2SUCCESS(true); } +/** + * Function that is called when the PHP engine initializes with a different PHP-CPP + * version for the libphpcpp.so file than the version the extension was compiled for + * @param type Module type + * @param number Module number + * @param tsrm_ls + * @return int 0 on success + */ +int ExtensionImpl::processMismatch(int type, int module_number TSRMLS_DC) +{ + // get the extension + auto *extension = find(module_number TSRMLS_CC); + + // report a warning + warning << "Version mismatch between PHP-CPP and extension " << extension->name() << " " << extension->version() << " (recompile needed?)" << std::endl; + + // done + return BOOL2SUCCESS(true); +} + /** * Constructor * @param data Pointer to the extension object created by the extension programmer * @param name Name of the extension * @param version Version number + * @param apiversion API version number */ -ExtensionImpl::ExtensionImpl(Extension *data, const char *name, const char *version) : ExtensionBase(data) +ExtensionImpl::ExtensionImpl(Extension *data, const char *name, const char *version, int apiversion) : + ExtensionBase(data) { // keep extension pointer based on the name name2extension[name] = this; @@ -262,6 +284,17 @@ ExtensionImpl::ExtensionImpl(Extension *data, const char *name, const char *vers _entry.globals_ptr = NULL; #endif + // everything is ok if the api versions match + if (apiversion == PHPCPP_API_VERSION) return; + + // mismatch between api versions, the extension is invalid, we use a + // different startup function to report to the user + _entry.module_startup_func = &ExtensionImpl::processMismatch; + + // the other callback functions are no longer necessary + _entry.module_shutdown_func = nullptr; + _entry.request_startup_func = nullptr; + _entry.request_shutdown_func = nullptr; } /** @@ -276,6 +309,26 @@ ExtensionImpl::~ExtensionImpl() if (_entry.functions) delete[] _entry.functions; } +/** + * The extension name + * @return const char * + */ +const char *ExtensionImpl::name() const +{ + // name is stored in the struct + return _entry.name; +} + +/** + * The extension version + * @return const char * + */ +const char *ExtensionImpl::version() const +{ + // version is stored in the struct + return _entry.version; +} + /** * Retrieve the module entry * @return zend_module_entry @@ -285,6 +338,10 @@ zend_module_entry *ExtensionImpl::module() // check if functions were already defined if (_entry.functions) return &_entry; + // if the 'processMismatch' function is installed, the API version is wrong, + // and nothing should be initialized + if (_entry.module_startup_func == &ExtensionImpl::processMismatch) return &_entry; + // the number of functions int count = _data->functions(); -- cgit v1.2.3