dump: Fix concurrency problem with dump files (#4757)

* dump: Fix concurrency problem with dump files

This adds the process ID for the cppcheck process to the filenames
of the .dump and .ctu-info files that the process generates.

So
  lib/cppcheck.cpp.dump
becomes
  lib/cppcheck.cpp.<PID>.dump

For example:
  lib/cppcheck.cpp.2637871.dump

The reason for this change is that if there is a buildsystem which
supports concurrency, multiple instances of cppcheck may be run for
the same file.  For example, if the same file is compiled in multiple
build variants, or for multiple targets.

If running the MISRA plugin over such a project with concurrency
enabled in the buildsystem, the plugin ends up crashing as multiple
jobs attempt to create/trample/delete the same files while other
jobs are using them.

For more information see:
    https://sourceforge.net/p/cppcheck/discussion/general/thread/02c757b4af/

* dump: Include pid in filename if dump not explicit

Only change the dump and ctu-info filenames to include the PID if
they are being generated due to an addon.

This means that existing scripts that use `--dump` will still work
if they depend on the previous naming behaviour. The more robust
filenames containing the pid will be used when the dump files are
used as an internal implementation detail for passing data to addons.

However this means that anything that does explicitly use `--dump`
will be susceptible to concurrency problems.

* test: Update addon dump file test to account for pid

This test causes a dump file to be created by enabling the misra
addon. Since the dump files now include the cppcheck process pid
this test had to be updated to account for the change.
This commit is contained in:
Michael Drake 2023-02-13 19:54:21 +00:00 committed by GitHub
parent 26bb55154f
commit d651b6baf1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 3 deletions

View File

@ -56,6 +56,12 @@
#include <utility>
#include <vector>
#ifndef _WIN32
#include <unistd.h>
#else
#include <process.h>
#endif
#define PICOJSON_USE_INT64
#include <picojson.h>
@ -229,13 +235,29 @@ static std::vector<std::string> split(const std::string &str, const std::string
return ret;
}
static int getPid()
{
#ifndef _WIN32
return getpid();
#else
return _getpid();
#endif
}
static std::string getDumpFileName(const Settings& settings, const std::string& filename)
{
if (!settings.dumpFile.empty())
return settings.dumpFile;
std::string extension;
if (settings.dump)
extension = ".dump";
else
extension = "." + std::to_string(getPid()) + ".dump";
if (!settings.dump && !settings.buildDir.empty())
return AnalyzerInformation::getAnalyzerInfoFile(settings.buildDir, filename, emptyString) + ".dump";
return filename + ".dump";
return AnalyzerInformation::getAnalyzerInfoFile(settings.buildDir, filename, emptyString) + extension;
return filename + extension;
}
static std::string getCtuInfoFileName(const std::string &dumpFile)

View File

@ -5,6 +5,7 @@ import os
import re
import tempfile
import pytest
import glob
from testutils import create_gui_project_file, cppcheck
@ -187,7 +188,12 @@ def test_build_dir_dump_output():
cppcheck(args.split())
cppcheck(args.split())
with open(f'{tempdir}/main.a1.dump', 'rt') as f:
filename = f'{tempdir}/main.a1.*.dump'
filelist = glob.glob(filename)
assert(len(filelist) == 1)
with open(filelist[0], 'rt') as f:
dump = f.read()
assert '</dump>' in dump, 'invalid dump data: ...' + dump[-100:]