C helgrind中的libxml2多线程错误
我有以下非常简单的程序:C helgrind中的libxml2多线程错误,c,multithreading,valgrind,libxml2,race-condition,C,Multithreading,Valgrind,Libxml2,Race Condition,我有以下非常简单的程序: #include <stdlib.h> #include <stdio.h> #include <pthread.h> #include <libxml/parser.h> #include <libxml/catalog.h> #include <libxml/tree.h> #include <libxml/HTMLparser.h> static const int kHTMLP
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <libxml/parser.h>
#include <libxml/catalog.h>
#include <libxml/tree.h>
#include <libxml/HTMLparser.h>
static const int kHTMLParseFlags =
HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING | HTML_PARSE_NONET;
void* test1(void* ptr)
{
htmlDocPtr doc = htmlReadFile("http://www.google.com", NULL, kHTMLParseFlags);
xmlFreeDoc(doc);
}
void* test2(void* ptr)
{
htmlDocPtr doc = htmlReadFile("http://www.lenta.ru", NULL, kHTMLParseFlags);
xmlFreeDoc(doc);
}
int main(void)
{
xmlInitParser();
xmlInitializeCatalog();
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, &test1, NULL);
pthread_create(&thread2, NULL, &test2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
xmlCatalogCleanup();
xmlCleanupParser();
return EXIT_SUCCESS;
}
这确实是libxml2中的一个bug。线程不安全(应使用原子增量或锁):
libxml2文档指出。我建议您和/或在上提出这个问题。我不知道这是否有关联,但此人说“只有当流程使用完库和所有用库构建的XML/HTML文档后,才应该调用xmlcleanuparser()。”似乎您在这里误用了它。顺便说一句,它添加了“警告:如果您的应用程序是多线程的或具有插件支持,那么如果另一个线程或插件仍在使用libxml2,则调用此函数可能会使应用程序崩溃”。请参阅我更新的代码。还有一些竞态条件。我不明白你的代码中会出现哪种竞态条件,你能发布valgrind的输出吗?添加了
valgrind
的示例输出只是为了确定一下,你是否用--with threads编译了库?
==2276== Possible data race during read of size 4 at 0x5EC2020 by thread #3
==2276== Locks held: none
==2276== at 0x4EE5117: xmlCatalogXMLResolve (catalog.c:1637)
==2276== by 0x4EE4F15: xmlCatalogListXMLResolve (catalog.c:2064)
==2276== by 0x4EE5FBE: xmlACatalogResolve (catalog.c:2875)
==2276== by 0x4EA21EA: xmlResolveResourceFromCatalog (xmlIO.c:4000)
==2276== by 0x4EA46C3: xmlDefaultExternalEntityLoader (xmlIO.c:4065)
==2276== by 0x4EA452E: xmlLoadExternalEntity (xmlIO.c:4133)
==2276== by 0x4EB9D88: htmlCreateFileParserCtxt (HTMLparser.c:6314)
==2276== by 0x4EBA97C: htmlReadFile (HTMLparser.c:6796)
==2276== by 0x400A18: test2(void*) (in /home/a.out)
==2276== by 0x4C32DF6: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==2276== by 0x51AC6A9: start_thread (pthread_create.c:333)
==2276==
==2276== This conflicts with a previous write of size 4 by thread #2
==2276== Locks held: none
==2276== at 0x4EE5131: xmlCatalogXMLResolve (catalog.c:1643)
==2276== by 0x4EE4F15: xmlCatalogListXMLResolve (catalog.c:2064)
==2276== by 0x4EE5FBE: xmlACatalogResolve (catalog.c:2875)
==2276== by 0x4EA21EA: xmlResolveResourceFromCatalog (xmlIO.c:4000)
==2276== by 0x4EA46C3: xmlDefaultExternalEntityLoader (xmlIO.c:4065)
==2276== by 0x4EA452E: xmlLoadExternalEntity (xmlIO.c:4133)
==2276== by 0x4EB9D88: htmlCreateFileParserCtxt (HTMLparser.c:6314)
==2276== by 0x4EBA97C: htmlReadFile (HTMLparser.c:6796)
==2276== Address 0x5ec2020 is 64 bytes inside a block of size 80 alloc'd
==2276== at 0x4C2CFEF: malloc (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==2276== by 0x4EE2D3F: xmlNewCatalogEntry (catalog.c:280)
==2276== by 0x4EE3340: xmlParseXMLCatalogOneNode (catalog.c:1187)
==2276== by 0x4EE3871: xmlParseXMLCatalogNode (catalog.c:1256)
==2276== by 0x4EE3871: xmlParseXMLCatalogNodeList (catalog.c:1323)
==2276== by 0x4EE4C3E: xmlParseXMLCatalogFile (catalog.c:1388)
==2276== by 0x4EE4C3E: xmlFetchXMLCatalogFile (catalog.c:1453)
==2276== by 0x4EE4FEF: xmlCatalogListXMLResolve (catalog.c:2061)
==2276== by 0x4EE5FBE: xmlACatalogResolve (catalog.c:2875)
==2276== by 0x4EA21EA: xmlResolveResourceFromCatalog (xmlIO.c:4000)
==2276== by 0x4EA46C3: xmlDefaultExternalEntityLoader (xmlIO.c:4065)
==2276== by 0x4EA452E: xmlLoadExternalEntity (xmlIO.c:4133)
==2276== by 0x4EB9D88: htmlCreateFileParserCtxt (HTMLparser.c:6314)
==2276== by 0x4EBA97C: htmlReadFile (HTMLparser.c:6796)
==2276== Block was alloc'd by thread #2
if (catal->depth > MAX_CATAL_DEPTH) {
xmlCatalogErr(catal, NULL, XML_CATALOG_RECURSION,
"Detected recursion in catalog %s\n",
catal->name, NULL, NULL);
return(NULL);
}
catal->depth++;