Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:72831 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 95168 invoked from network); 26 Feb 2014 17:24:38 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 26 Feb 2014 17:24:38 -0000 Authentication-Results: pb1.pair.com smtp.mail=oneil@saxonica.com; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=oneil@saxonica.com; sender-id=unknown Received-SPF: error (pb1.pair.com: domain saxonica.com from 217.69.47.236 cause and error) X-PHP-List-Original-Sender: oneil@saxonica.com X-Host-Fingerprint: 217.69.47.236 uk1rly2283.eechost.net Linux 2.6 Received: from [217.69.47.236] ([217.69.47.236:55630] helo=uk1rly2283.eechost.net) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 54/E2-12475-4532E035 for ; Wed, 26 Feb 2014 12:24:37 -0500 Received: from [82.152.109.199] (helo=[192.168.0.106]) by uk1rly2283.eechost.net with esmtpa (Exim 4.72) (envelope-from ) id 1WIiE3-0003Ou-6K; Wed, 26 Feb 2014 17:24:55 +0000 Message-ID: <530E234E.3010709@saxonica.com> Date: Wed, 26 Feb 2014 17:24:30 +0000 Organization: Saxonica User-Agent: Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 MIME-Version: 1.0 To: =?UTF-8?B?Sm9oYW5uZXMgU2NobMO8dGVy?= CC: internals@lists.php.net References: <530E0F02.2060707@saxonica.com> <1393433357.29544.3.camel@guybrush> In-Reply-To: <1393433357.29544.3.camel@guybrush> Content-Type: multipart/alternative; boundary="------------070204030209060801070701" X-Auth-Info: oneil@saxonica.com (plain) Subject: Re: [PHP-DEV] Thread safety issue in C++ extension module From: oneil@saxonica.com (O'Neil Delpratt) --------------070204030209060801070701 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit On 26/02/14 16:49, Johannes Schlüter wrote: > Yes, TSRM is our thread-safe resource manager providing a thread local > storage for PHP request isolation. > > The information in your message is sparse though. Without any code, > examples of crashes etc it is hard to see what you are actually doing, > where you are stuck and how to help. Thanks for your quick response. Please find code below: I have commented out my attempt to do some thread safety. I have cut out some PHP_METHODS to ease the readability. The line of code of interest is indicated by //**** in two places. Specifically, where we create the SaxonProcessor object and also destroy the JVM needs to be in a single os process (i.e.: "saxonProc = new SaxonProcessor(false); " and "obj->saxonProc->close();" ) =============================== #ifndef PHP_SAXON_H #define PHP_SAXON_H #define PHP_SAXON_EXTNAME "Saxon/C" #define PHP_SAXON_EXTVER "0.2" #ifdef HAVE_CONFIG_H #include "config.h" #endif /*#ifdef ZTS #include "TSRM.h" #define COUNTER_G(v) TSRMG(counter_globals_id, zend_counter_globals *, v) #else #define COUNTER_G(v) (counter_globals.v) #endif*/ extern "C" { #ifdef __linux__ #include "php.h" #include "ext/standard/info.h" #endif #include "zend_exceptions.h" } /*ZEND_BEGIN_MODULE_GLOBALS(saxon) long counter; ZEND_END_MODULE_GLOBALS(saxon) ZEND_DECLARE_MODULE_GLOBALS(saxon) int saxon_globals_id; */ extern zend_module_entry saxon_module_entry; #define phpext_saxon_ptr &saxon_module_entry; zend_object_handlers XsltProcessor_object_handlers; zend_object_handlers XQueryProcessor_object_handlers; zend_object_handlers xdmValue_object_handlers; struct SaxonProcessor_object { zend_object std; SaxonProcessor * saxonProc; }; struct XsltProcessor_object { zend_object std; XsltProcessor *xsltProcessor; SaxonProcessor * saxonProc; }; struct xdmValue_object { zend_object std; XdmValue * xdmValue; }; zend_class_entry *xsltProcessor_ce; zend_class_entry *xqueryProcessor_ce; zend_class_entry *xdmValue_ce; void XsltProcessor_free_storage(void *object TSRMLS_DC) { php_error(E_WARNING, "XXXXXXXXXXXXXXXX - free storage"); XsltProcessor_object *obj = (XsltProcessor_object *)object; if (obj->saxonProc != NULL) { obj->saxonProc->close(); //**** - CONTAINS CODE THAT CAN ONLY BE RUN IN SINGLE OS PROCESS } delete obj->saxonProc; delete obj->xsltProcessor; zend_hash_destroy(obj->std.properties); FREE_HASHTABLE(obj->std.properties); efree(obj); } zend_object_value XsltProcessor_create_handler(zend_class_entry *type TSRMLS_DC) { zval *tmp; zend_object_value retval; XsltProcessor_object *obj = (XsltProcessor_object *)emalloc(sizeof(XsltProcessor_object)); memset(obj, 0, sizeof(XsltProcessor_object)); obj->std.ce = type; ALLOC_HASHTABLE(obj->std.properties); zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); retval.handle = zend_objects_store_put(obj, NULL, XsltProcessor_free_storage, NULL TSRMLS_CC); retval.handlers = &XsltProcessor_object_handlers; return retval; } PHP_METHOD(Xslt2Processor, __construct) { char cwd[256]; getcwd(cwd, sizeof(cwd)); if (getcwd(cwd, sizeof(cwd)) == NULL) { php_error(E_WARNING,"getcwd error"); } XsltProcessor *xsltProcessor = NULL; zval *object = getThis(); SaxonProcessor * saxonProc; SaxonProcessor_object *saxonProcObj = (SaxonProcessor_object *)zend_object_store_get_object(object TSRMLS_CC); SaxonProcessor * saxonProc = saxonProcObj->saxonProc; if(saxonProc == NULL) { saxonProc = new SaxonProcessor(false); //**** - CONTAINS CODE THAT CAN ONLY BE RUN IN SINGLE OS PROCESS saxonProcObj->saxonProc = saxonProc; } saxonProc->setcwd(cwd); XsltProcessor_object *obj = (XsltProcessor_object *)zend_object_store_get_object(object TSRMLS_CC); obj->saxonProc = saxonProc; /*saxonProc = obj->saxonProc; if(saxonProc == NULL) { php_error(E_WARNING, "Xslt2Processor Construct - call to SAxonProcessor"); saxonProc = new SaxonProcessor(false); obj->saxonProc = saxonProc; } saxonProc->setcwd(cwd);*/ xsltProcessor = saxonProc->newTransformer(); obj->xsltProcessor = xsltProcessor; } PHP_METHOD(Xslt2Processor, __destruct) { XsltProcessor_object *obj = (XsltProcessor_object *)zend_object_store_get_object( getThis() TSRMLS_CC); SaxonProcessor_object *obj2 = (SaxonProcessor_object *)zend_object_store_get_object( getThis() TSRMLS_CC); XsltProcessor *xsltProcessor = obj->xsltProcessor; SaxonProcessor * saxonProc= obj2->saxonProc; delete xsltProcessor; delete saxonProc } PHP_METHOD(Xslt2Processor, xsltSaveResultToFile) { XsltProcessor *xsltProcessor; char * sourcefile; char * stylesheet; char * outputfile; int len1, len2, len3; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &sourcefile, &len1, &stylesheet, &len2, &outputfile, &len3) == FAILURE) { RETURN_NULL(); } XsltProcessor_object *obj = (XsltProcessor_object *)zend_object_store_get_object( getThis() TSRMLS_CC); xsltProcessor = obj->xsltProcessor; if (xsltProcessor != NULL) { xsltProcessor->xsltSaveResultToFile(sourcefile, stylesheet, outputfile); if(xsltProcessor->exceptionOccurred()) { //throw exception } } } PHP_METHOD(Xslt2Processor, xsltApplyStylesheet) { XsltProcessor *xsltProcessor; char * sourcefile; char * stylesheet; int len1, len2, myint; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &sourcefile, &len1, &stylesheet, &len2) == FAILURE) { RETURN_NULL(); } XsltProcessor_object *obj = (XsltProcessor_object *)zend_object_store_get_object( getThis() TSRMLS_CC); xsltProcessor = obj->xsltProcessor; if (xsltProcessor != NULL) { const char * result = xsltProcessor->xsltApplyStylesheet(sourcefile, stylesheet); xsltProcessor->checkException(); if(result != NULL ) { char *str = estrdup(result); RETURN_STRING(str, 0); } } RETURN_NULL(); } zend_function_entry XsltProcessor_methods[] = { PHP_ME(Xslt2Processor, __construct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) PHP_ME(Xslt2Processor, __destruct, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_DTOR) PHP_ME(Xslt2Processor, xsltSaveResultToFile, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, xsltApplyStylesheet, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, xsltApplyStylesheet1, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, setSourceValue, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, parseString, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, setParameter, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, setProperty, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, clear, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, exceptionClear, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, close, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, getErrorCode, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, getErrorMessage, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, getExceptionCount, NULL, ZEND_ACC_PUBLIC) PHP_ME(Xslt2Processor, version, NULL, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; PHP_MINIT_FUNCTION(saxon) { // ts_allocate_id(&saxon_globals_id, sizeof(XsltProcessor_object), (ts_allocate_ctor)XsltProcessor_object,(ts_allocate_dtor)XsltProcessor_object); zend_class_entry ce; INIT_CLASS_ENTRY(ce, "Xslt2Processor", XsltProcessor_methods); xsltProcessor_ce = zend_register_internal_class(&ce TSRMLS_CC); xsltProcessor_ce->create_object = XsltProcessor_create_handler; memcpy(&XsltProcessor_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); XsltProcessor_object_handlers.clone_obj = NULL; INIT_CLASS_ENTRY(ce, "XQueryProcessor", XQueryProcessor_methods); xqueryProcessor_ce = zend_register_internal_class(&ce TSRMLS_CC); xqueryProcessor_ce->create_object = XQueryProcessor_create_handler; memcpy(&XQueryProcessor_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); XQueryProcessor_object_handlers.clone_obj = NULL; INIT_CLASS_ENTRY(ce, "XdmValue", xdmValue_methods); xdmValue_ce = zend_register_internal_class(&ce TSRMLS_CC); xdmValue_ce->create_object = xdmValue_create_handler; memcpy(&xdmValue_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); xdmValue_object_handlers.clone_obj = NULL; // ZEND_INIT_MODULE_GLOBALS(saxon, php_saxon_init_globals,NULL); // REGISTER_INI_ENTRIES(); return SUCCESS; } // function implementation PHP_MINFO_FUNCTION(saxon) { php_info_print_table_start(); php_info_print_table_header(2, "Saxon/C", "enabled"); php_info_print_table_row(2, "Saxon/C EXT version", "0.2"); php_info_print_table_row(2, "Saxon-HEJ", "9.5.1.3"); php_info_print_table_row(2, "Excelsior JET (MP1)", "9.0"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); } PHP_MSHUTDOWN_FUNCTION(saxon){ php_error(E_WARNING,"entered MSHUTDOWN"); UNREGISTER_INI_ENTRIES(); return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(saxon){ php_error(E_WARNING,"entered RSHUTDOWN"); efree(xsltProcessor_ce); return SUCCESS; } PHP_RINIT_FUNCTION(saxon){ php_error(E_WARNING,"entered RINT"); /* string str = ""+((SAXON_G(counter))); const char * result = str.c_str(); php_error(E_WARNING, result); SAXON_G(counter) = 0;*/ return SUCCESS; } zend_module_entry saxon_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_SAXON_EXTNAME, NULL/*saxon_static_functions*/, /* Functions */ PHP_MINIT(saxon), /* MINIT */ PHP_MSHUTDOWN(saxon), /* MSHUTDOWN */ /*PHP_RINIT(saxon)*/NULL, /* RINIT */ PHP_RSHUTDOWN(saxon), /* RSHUTDOWN */ PHP_MINFO(saxon), /* MINFO */ #if ZEND_MODULE_API_NO >= 20010901 PHP_SAXON_EXTVER, #endif STANDARD_MODULE_PROPERTIES }; //#ifdef COMPILE_DL_SAXON extern "C" { ZEND_GET_MODULE(saxon) } //#endif =================== kind regards, -- O'Neil Delpratt Software Developer, Saxonica Limited Email: oneil@saxonica.com Tel: +44 118 946 5894 Web: http://www.saxonica.com Saxonica Community Site: http://dev.saxonica.com Saxonica Bug tracking System: https://saxonica.plan.io/ --------------070204030209060801070701--