After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 168327 - Segmentation fault when calling xsltFreeTransformContext() in multi-threaded program
Segmentation fault when calling xsltFreeTransformContext() in multi-threaded ...
Status: VERIFIED NOTABUG
Product: libxslt
Classification: Platform
Component: general
1.1.12
Other All
: High critical
: ---
Assigned To: Daniel Veillard
libxml QA maintainers
Depends on:
Blocks:
 
 
Reported: 2005-02-23 23:45 UTC by Jun Zhang
Modified: 2009-08-15 18:40 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Jun Zhang 2005-02-23 23:45:40 UTC
Steps to reproduce:
Comiple the following C program (ctxt.c) using the following command (you may 
change the paths for the lib and include for your own environment):

gcc -o ctxt ctxt.c -I/x/contrib/libxml2-2.6.17/include/libxml2 -
L/x/contrib/libxml2-2.6.17/lib -lxml2  -I/x/contrib/libxslt-1.1.12/include -
L/x/contrib/libxslt-1.1.12/lib -lxslt -g -lpthread

Copy the attached xsl file (test.xsl) and xml file (test.xml) to the current 
directory, then do:

./ctxt test.xsl test.xml > /dev/null

You will see a core dumped in a few seconds. I noticed the problem is mainly 
caused by the 'variable' declaration in test.xsl, if I remove that line, the 
program runs fine without a problem. So I think xsltFreeGlobalVariables() 
(called by xsltFreeTransformContext() in this case) is not thread safe. 

Source code for the C program (ctxt.c):

/*
 * Testing xslt
 */
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
#include <sys/types.h>
#include <libxml/SAX.h>
#include <libxml/entities.h>
#include <libxml/encoding.h>
#include <libxml/parserInternals.h>
#include <libxml/xmlerror.h>
#include <libxml/HTMLparser.h>
#include <libxml/HTMLtree.h>
#include <libxml/debugXML.h>
#include <libxml/tree.h>
#include <libxml/list.h>
#include <libxml/hash.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
#include <libxml/xpointer.h>
#include <libxml/xinclude.h>
#include <libxml/xmlIO.h>
#include <libxml/xmlmemory.h>
#include <libxml/nanohttp.h>
#include <libxml/nanoftp.h>
#include <libxml/uri.h>
#include <libxml/valid.h>
#include <libxml/xlink.h>

#include <libxml/xmlversion.h>
#include <libxml/catalog.h>
#include <libxml/threads.h>
#include <libxml/globals.h>
#include <libxml/c14n.h>
#include <libxml/xmlautomata.h>
#include <libxml/xmlregexp.h>
#include <libxml/xmlschemas.h>
#include <libxml/schemasInternals.h>
#include <libxml/xmlschemastypes.h>
#include <libxml/xmlunicode.h>
#include <libxml/xmlreader.h>
#include <libxml/relaxng.h>
#include <libxml/SAX2.h>
#include <libxml/xmlexports.h>
#include <libxml/xmlwriter.h>
#include <libxml/chvalid.h>
#include <libxml/pattern.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltutils.h>
#include <libxslt/pattern.h>

#include <libxslt/templates.h>
#include <libxslt/variables.h>
#include <libxslt/keys.h>
#include <libxslt/numbersInternals.h>
#include <libxslt/extensions.h>
#include <libxslt/extra.h>
#include <libxslt/functions.h>
#include <libxslt/namespaces.h>
#include <libxslt/imports.h>
#include <libxslt/attributes.h>
#include <libxslt/documents.h>
#include <libxslt/preproc.h>
#include <libxslt/transform.h>
#include <libxslt/security.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/xsltconfig.h>
#include <libxslt/xsltexports.h>
#include <libexslt/exsltconfig.h>
#include <libexslt/exslt.h>

void     timeout();
xsltStylesheetPtr xsl_cur = NULL;
char xml_file[100];

 
/*
 * the thread code that processes xslt requests
 */
void *generate_html(void *ns) {
	xmlDocPtr results_info;
	xsltTransformContextPtr ctxt;
	xmlDocPtr result = NULL;
    xmlChar * result_xmlchar;
    int result_len;
    int nbytes;

	results_info = xmlParseFile(xml_file);
	ctxt = xsltNewTransformContext(xsl_cur, results_info);

    result = xsltApplyStylesheetUser(xsl_cur,
                                         results_info,
                                         NULL, // style_params,
                                         NULL, // output
                                         NULL, // profile
                                         ctxt); // context

    nbytes = xsltSaveResultToString(&result_xmlchar,
                                        &result_len,
                                        result,
                                        xsl_cur);

	printf("result: %s\n", result_xmlchar);
    xmlFreeDoc(result);
    xmlFreeDoc(results_info);
    xmlFree(result_xmlchar);
    xsltFreeTransformContext(ctxt);

	pthread_exit(NULL);
}

main(int argc, char *argv[]) {
	pthread_t t;
	int rc;
	int i, j;
	xmlDocPtr xsl_style = NULL;
	xmlGlobalState gs;
	xmlInitializeGlobalState(&gs);

	if (argc < 3) {
		fprintf(stderr, "Usage: ctxt xsl_file xml_file\n");
		exit(1);
	}

	printf("version=%s\n", LIBXSLT_DOTTED_VERSION);
	printf("version=%s\n", LIBXML_DOTTED_VERSION);
	strcpy(xml_file, argv[2]);
	xsl_style = xmlReadFile(argv[1], NULL, XSLT_PARSE_OPTIONS);

	if (xsl_style == NULL) {
		printf("ERROR: read xsl file: %s\n", argv[1]);
		exit(1);
	}

	xsl_cur =  xsltParseStylesheetDoc(xsl_style);

	if (xsl_cur == NULL) {
		printf("ERROR: load xsl file: %s\n", argv[1]);
	}

	while (1) {
		sleep(1);
		for (j = 0; j < 10; j++) {
      		rc = pthread_create(&t, NULL, generate_html, (void *)0);
      		if (rc){
       	  		printf("ERROR; return code from pthread_create() is %
d\n", rc);
         		exit(-1);
      		}
			pthread_detach(t);
		}
	}
}


test.xsl

<?xml version="1.0"?><xst:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xst="http://www.w3.org/1999/XSL/Transform">
<xst:output indent="yes" method="html" />
<xst:strip-space elements="*" />
<xst:variable name="PPRD" select="/ResultDoc" />
<xst:template match="/ResultDoc">
<html>
</html>
</xst:template>
</xst:stylesheet>

test.xml:

<ResultDoc xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Properties>
        <Length>1000</Length>
    </Properties>
</ResultDoc>



Stack trace:
  • #0 xmlXPathFreeNodeSet__internal_alias
    at xpath.c line 2221
  • #0 xmlXPathFreeNodeSet__internal_alias
    at xpath.c line 2221
  • #1 xmlXPathFreeObject__internal_alias
    at xpath.c line 3417
  • #2 xsltFreeStackElem
    at variables.c line 223
  • #3 xmlHashFree__internal_alias
    at hash.c line 284
  • #4 xsltFreeGlobalVariables
    at variables.c line 1556
  • #5 xsltFreeTransformContext
    at transform.c line 505
  • #6 generate_html
    at ctxt.c line 110
  • #7 pthread_start_thread
    at manager.c line 241
  • #8 thread_start
    from /lib/libc.so.6

Other information:
I am running it on Linux
Comment 1 William M. Brack 2005-02-24 07:32:48 UTC
This problem is nothing to do with threads, but rather is an error in your
coding.  Within the routine "generate_html", at the end, you have code to free
the resources.  This, of course, is a proper thing to do.  However, care must be
taken to assure the resources are freed in the proper order.

The parsed xml document "results_info" is used by the xslt transformation
context, so when you free that document before freeing the context which is
using it, the crash occurs.  A good general rule to follow is to always free the
resources in the reverse order from which they were related.

When I made that change, and also reduced the sleep time down to 50
milliseconds, on my reasonably-fast dual-Athlon system there was no problem (ran
for about 1/2 hour).

One other unrelated point - although it is certainly not an error, when you have
a #include for almost every possible libxml2 and libxslt include file, it makes
the program a bit difficult to digest :-).  For this particular example program,
only three includes are really needed -
#include <libxml/parser.h>      /* for libxml2 parsing */
#include <libxslt/transform.h>  /* for libxslt transformations */
#include <libxslt/xsltutils.h>  /* for XSLT_DOTTED_VERSION */

Hope that's helpful -

Bill
Comment 2 Jun Zhang 2005-02-24 18:13:40 UTC
I changed the order or free's in my original code, it worked. Thanks for the 
quick response.