Tom Lane escribió: > We might be able to compromise by only resetting the context after > an error, but this is still only possible if we have a way to make > libxml let go of *all* pointers to alloc'd objects. I don't understand > your comment that xmlCleanupParser solves it --- we call that already, > and it doesn't seem to be preventing the problem.
With the attached patch, it doesn't crash, but I see the added WARNING four times in the log, which is proof that the cleanup thing is not called as the code seems to think. I wonder -- is this thing supposed to be reentrant? I think that's the whole problem with it. (I think what I'm doing in xml_init in the non-first case is bogus anyway -- but I post the patch to show my point.) -- Alvaro Herrera http://www.CommandPrompt.com/ PostgreSQL Replication, Consulting, Custom Development, 24x7 support
Index: src/backend/utils/adt/xml.c =================================================================== RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/adt/xml.c,v retrieving revision 1.64 diff -c -p -r1.64 xml.c *** src/backend/utils/adt/xml.c 1 Jan 2008 19:45:53 -0000 1.64 --- src/backend/utils/adt/xml.c 10 Jan 2008 00:37:32 -0000 *************** XmlOptionType xmloption; *** 80,85 **** --- 80,86 ---- #ifdef USE_LIBXML static StringInfo xml_err_buf = NULL; + static MemoryContext LibxmlContext = NULL; static void xml_init(void); static void *xml_palloc(size_t size); *************** xmlvalidate(PG_FUNCTION_ARGS) *** 844,849 **** --- 845,852 ---- xmlFreeParserCtxt(ctxt); ctxt = NULL; xmlCleanupParser(); + MemoryContextDelete(LibxmlContext); + LibxmlContext = NULL; } PG_CATCH(); { *************** xmlvalidate(PG_FUNCTION_ARGS) *** 858,863 **** --- 861,868 ---- if (ctxt) xmlFreeParserCtxt(ctxt); xmlCleanupParser(); + MemoryContextDelete(LibxmlContext); + LibxmlContext = NULL; PG_RE_THROW(); } *************** xml_init(void) *** 953,958 **** --- 958,969 ---- xmlSetGenericErrorFunc(NULL, xml_errorHandler); /* Set up memory allocation our way, too */ + Assert(LibxmlContext == NULL); + LibxmlContext = AllocSetContextCreate(PortalContext, + "LibxmlContext", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); xmlMemSetup(xml_pfree, xml_palloc, xml_repalloc, xml_pstrdup); /* Check library compatibility */ *************** xml_init(void) *** 974,979 **** --- 985,998 ---- * about, anyway. */ xmlSetGenericErrorFunc(NULL, xml_errorHandler); + if (LibxmlContext == NULL) + LibxmlContext = AllocSetContextCreate(PortalContext, + "LibxmlContext", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + else + elog(WARNING, "LibxmlContext already exists"); xmlMemSetup(xml_pfree, xml_palloc, xml_repalloc, xml_pstrdup); } } *************** xml_parse(text *data, XmlOptionType xmlo *** 1285,1290 **** --- 1304,1311 ---- xmlFreeParserCtxt(ctxt); ctxt = NULL; xmlCleanupParser(); + MemoryContextDelete(LibxmlContext); + LibxmlContext = NULL; } PG_CATCH(); { *************** xml_parse(text *data, XmlOptionType xmlo *** 1293,1298 **** --- 1314,1321 ---- if (ctxt) xmlFreeParserCtxt(ctxt); xmlCleanupParser(); + MemoryContextDelete(LibxmlContext); + LibxmlContext = NULL; PG_RE_THROW(); } *************** xml_text2xmlChar(text *in) *** 1325,1331 **** static void * xml_palloc(size_t size) { ! return palloc(size); } --- 1348,1354 ---- static void * xml_palloc(size_t size) { ! return MemoryContextAlloc(LibxmlContext, size); } *************** xml_pfree(void *ptr) *** 1346,1352 **** static char * xml_pstrdup(const char *string) { ! return pstrdup(string); } --- 1369,1375 ---- static char * xml_pstrdup(const char *string) { ! return MemoryContextStrdup(LibxmlContext, string); } *************** xpath(PG_FUNCTION_ARGS) *** 3368,3374 **** "could not parse XML data"); xpathctx = xmlXPathNewContext(doc); if (xpathctx == NULL) ! xml_ereport(ERROR, ERRCODE_INTERNAL_ERROR, "could not allocate XPath context"); xpathctx->node = xmlDocGetRootElement(doc); if (xpathctx->node == NULL) --- 3391,3397 ---- "could not parse XML data"); xpathctx = xmlXPathNewContext(doc); if (xpathctx == NULL) ! xml_ereport(ERROR, ERRCODE_OUT_OF_MEMORY, "could not allocate XPath context"); xpathctx->node = xmlDocGetRootElement(doc); if (xpathctx->node == NULL) *************** xpath(PG_FUNCTION_ARGS) *** 3439,3444 **** --- 3462,3469 ---- xmlFreeParserCtxt(ctxt); ctxt = NULL; xmlCleanupParser(); + MemoryContextDelete(LibxmlContext); + LibxmlContext = NULL; } PG_CATCH(); { *************** xpath(PG_FUNCTION_ARGS) *** 3453,3458 **** --- 3478,3485 ---- if (ctxt) xmlFreeParserCtxt(ctxt); xmlCleanupParser(); + MemoryContextDelete(LibxmlContext); + LibxmlContext = NULL; PG_RE_THROW(); }
---------------------------(end of broadcast)--------------------------- TIP 4: Have you searched our list archives? http://archives.postgresql.org