diff options
author | Dimitri van Heesch <dimitri@stack.nl> | 2015-10-17 14:38:29 (GMT) |
---|---|---|
committer | Dimitri van Heesch <dimitri@stack.nl> | 2015-10-17 14:38:29 (GMT) |
commit | f196c9f1d69238a814ff3152103f3bd310efdf0d (patch) | |
tree | 7a2d421a6aaef05940d57723816999e4cbd7265c /src/dot.cpp | |
parent | ffff69548813cd6c018973c3c0ae8b06b5e3eadc (diff) | |
download | Doxygen-f196c9f1d69238a814ff3152103f3bd310efdf0d.zip Doxygen-f196c9f1d69238a814ff3152103f3bd310efdf0d.tar.gz Doxygen-f196c9f1d69238a814ff3152103f3bd310efdf0d.tar.bz2 |
Bug 756241 - Race condition in parallel DOT runs
Diffstat (limited to 'src/dot.cpp')
-rw-r--r-- | src/dot.cpp | 82 |
1 files changed, 38 insertions, 44 deletions
diff --git a/src/dot.cpp b/src/dot.cpp index 701f868..2f245f6 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -659,10 +659,9 @@ static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, // since dot silently reproduces the input file when it does not // support the PNG format, we need to check the result. -static void checkDotResult(const QCString &imgName) +static void checkDotResult(const char *imgExt, const char *imgName) { - QCString imgExt = getDotImageExtension(); - if (imgExt=="png") + if (qstrcmp(imgExt,"png")==0) { FILE *f = portable_fopen(imgName,"rb"); if (f) @@ -675,19 +674,19 @@ static void checkDotResult(const QCString &imgName) err("Image `%s' produced by dot is not a valid PNG!\n" "You should either select a different format " "(DOT_IMAGE_FORMAT in the config file) or install a more " - "recent version of graphviz (1.7+)\n",imgName.data() + "recent version of graphviz (1.7+)\n",imgName ); } } else { - err("Could not read image `%s' generated by dot!\n",imgName.data()); + err("Could not read image `%s' generated by dot!\n",imgName); } fclose(f); } else { - err("Could not open image `%s' generated by dot!\n",imgName.data()); + err("Could not open image `%s' generated by dot!\n",imgName); } } } @@ -793,54 +792,46 @@ int DotNodeList::compareValues(const DotNode *n1,const DotNode *n2) const DotRunner::DotRunner(const QCString &file,const QCString &path, bool checkResult,const QCString &imageName) - : m_file(file), m_path(path), - m_checkResult(checkResult), m_imageName(imageName) -{ - static bool dotCleanUp = Config_getBool("DOT_CLEANUP"); - m_cleanUp = dotCleanUp; + : m_dotExe(Config_getString("DOT_PATH")+"dot"), + m_file(file), m_path(path), + m_checkResult(checkResult), m_imageName(imageName), + m_imgExt(getDotImageExtension()) +{ + static bool dotCleanUp = Config_getBool("DOT_CLEANUP"); + static bool dotMultiTargets = Config_getBool("DOT_MULTI_TARGETS"); + m_cleanUp = dotCleanUp; + m_multiTargets = dotMultiTargets; m_jobs.setAutoDelete(TRUE); } void DotRunner::addJob(const char *format,const char *output) { QCString args = QCString("-T")+format+" -o \""+output+"\""; - m_jobs.append(new QCString(args)); + m_jobs.append(new DotConstString(args)); } void DotRunner::addPostProcessing(const char *cmd,const char *args) { - m_postCmd = cmd; - m_postArgs = args; + m_postCmd.set(cmd); + m_postArgs.set(args); } bool DotRunner::run() { int exitCode=0; - // we need to use data here to make a copy of the string, as Config_getString can be called by - // multiple threads simulaneously and the reference counting is not thread safe. - QCString dotExe = Config_getString("DOT_PATH").data(); - dotExe+="dot"; - bool multiTargets = Config_getBool("DOT_MULTI_TARGETS"); QCString dotArgs; - QListIterator<QCString> li(m_jobs); - QCString *s; - QCString file = m_file; - QCString path = m_path; - QCString imageName = m_imageName; - QCString postCmd = m_postCmd; - QCString postArgs = m_postArgs; - bool checkResult = m_checkResult; - bool cleanUp = m_cleanUp; - if (multiTargets) - { - dotArgs="\""+file+"\""; + QListIterator<DotConstString> li(m_jobs); + DotConstString *s; + if (m_multiTargets) + { + dotArgs=QCString("\"")+m_file.data()+"\""; for (li.toFirst();(s=li.current());++li) { dotArgs+=' '; - dotArgs+=*s; + dotArgs+=s->data(); } - if ((exitCode=portable_system(dotExe,dotArgs,FALSE))!=0) + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) { goto error; } @@ -849,30 +840,33 @@ bool DotRunner::run() { for (li.toFirst();(s=li.current());++li) { - dotArgs="\""+file+"\" "+*s; - if ((exitCode=portable_system(dotExe,dotArgs,FALSE))!=0) + dotArgs=QCString("\"")+m_file.data()+"\" "+s->data(); + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) { goto error; } } } - if (!postCmd.isEmpty() && portable_system(postCmd,postArgs)!=0) + if (!m_postCmd.isEmpty() && portable_system(m_postCmd.data(),m_postArgs.data())!=0) { err("Problems running '%s' as a post-processing step for dot output\n",m_postCmd.data()); return FALSE; } - if (checkResult) checkDotResult(imageName); - if (cleanUp) + if (m_checkResult) + { + checkDotResult(m_imgExt.data(),m_imageName.data()); + } + if (m_cleanUp) { //printf("removing dot file %s\n",m_file.data()); //QDir(path).remove(file); - m_cleanupItem.file = file; - m_cleanupItem.path = path; + m_cleanupItem.file.set(m_file.data()); + m_cleanupItem.path.set(m_path.data()); } return TRUE; error: err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n", - exitCode,dotExe.data(),dotArgs.data()); + exitCode,m_dotExe.data(),dotArgs.data()); return FALSE; } @@ -1202,7 +1196,7 @@ void DotWorkerThread::run() while ((runner=m_queue->dequeue())) { runner->run(); - DotRunner::CleanupItem cleanup = runner->cleanup(); + const DotRunner::CleanupItem &cleanup = runner->cleanup(); if (!cleanup.file.isEmpty()) { m_cleanupItems.append(new DotRunner::CleanupItem(cleanup)); @@ -1216,7 +1210,7 @@ void DotWorkerThread::cleanup() DotRunner::CleanupItem *ci; for (;(ci=it.current());++it) { - QDir(ci->path).remove(ci->file); + QDir(ci->path.data()).remove(ci->file.data()); } } @@ -4237,7 +4231,7 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir, return; } - if (format==GOF_BITMAP) checkDotResult(absImgName); + if (format==GOF_BITMAP) checkDotResult(getDotImageExtension(),absImgName); Doxygen::indexList->addImageFile(imgName); |