Fixed #1650 (Cppcheck deadlock)
http://sourceforge.net/apps/trac/cppcheck/ticket/1650
This commit is contained in:
parent
f5d3042635
commit
b5da0b8ed2
|
@ -27,6 +27,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <errno.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &errorLogger)
|
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &errorLogger)
|
||||||
|
@ -51,12 +52,15 @@ void ThreadExecutor::addFileContent(const std::string &path, const std::string &
|
||||||
|
|
||||||
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
|
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
|
||||||
|
|
||||||
bool ThreadExecutor::handleRead(unsigned int &result)
|
int ThreadExecutor::handleRead(unsigned int &result)
|
||||||
{
|
{
|
||||||
char type = 0;
|
char type = 0;
|
||||||
if (read(_pipe[0], &type, 1) <= 0)
|
if (read(_pipe[0], &type, 1) <= 0)
|
||||||
{
|
{
|
||||||
return false;
|
if( errno == EAGAIN )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != '1' && type != '2' && type != '3')
|
if (type != '1' && type != '2' && type != '3')
|
||||||
|
@ -104,10 +108,12 @@ bool ThreadExecutor::handleRead(unsigned int &result)
|
||||||
iss >> fileResult;
|
iss >> fileResult;
|
||||||
result += fileResult;
|
result += fileResult;
|
||||||
_errorLogger.reportStatus(_fileCount, _filenames.size());
|
_errorLogger.reportStatus(_fileCount, _filenames.size());
|
||||||
|
delete [] buf;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] buf;
|
delete [] buf;
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ThreadExecutor::check()
|
unsigned int ThreadExecutor::check()
|
||||||
|
@ -134,21 +140,12 @@ unsigned int ThreadExecutor::check()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int childCount = 0;
|
unsigned int childCount = 0;
|
||||||
for (unsigned int i = 0; i < _filenames.size(); i++)
|
unsigned int i = 0;
|
||||||
|
while( true )
|
||||||
{
|
{
|
||||||
// Keep only wanted amount of child processes running at a time.
|
// Start a new child
|
||||||
if (childCount >= _settings._jobs)
|
if( i < _filenames.size() && childCount < _settings._jobs )
|
||||||
{
|
{
|
||||||
while (handleRead(result))
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int stat = 0;
|
|
||||||
waitpid(0, &stat, 0);
|
|
||||||
--childCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
{
|
{
|
||||||
|
@ -180,19 +177,31 @@ unsigned int ThreadExecutor::check()
|
||||||
}
|
}
|
||||||
|
|
||||||
++childCount;
|
++childCount;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else if (childCount > 0)
|
||||||
|
{
|
||||||
|
// Wait for child to quit before stating new processes
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
int readRes = handleRead(result);
|
||||||
|
if( readRes == -1 )
|
||||||
|
break;
|
||||||
|
else if( readRes == 0 )
|
||||||
|
usleep(5000); // 5 ms
|
||||||
}
|
}
|
||||||
|
|
||||||
while (childCount > 0)
|
|
||||||
{
|
|
||||||
int stat = 0;
|
int stat = 0;
|
||||||
waitpid(0, &stat, 0);
|
waitpid(0, &stat, 0);
|
||||||
--childCount;
|
--childCount;
|
||||||
}
|
}
|
||||||
|
else if(childCount == 0)
|
||||||
while (handleRead(result))
|
|
||||||
{
|
{
|
||||||
|
// All done
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,13 @@ private:
|
||||||
|
|
||||||
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
|
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
|
||||||
private:
|
private:
|
||||||
bool handleRead(unsigned int &result);
|
/**
|
||||||
|
* Read from the pipe, parse and handle what ever is in there.
|
||||||
|
*@return -1 in case of error
|
||||||
|
* 0 if there is nothing in the pipe to be read
|
||||||
|
* 1 if we did read something
|
||||||
|
*/
|
||||||
|
int handleRead(unsigned int &result);
|
||||||
void writeToPipe(char type, const std::string &data);
|
void writeToPipe(char type, const std::string &data);
|
||||||
int _pipe[2];
|
int _pipe[2];
|
||||||
std::list<std::string> _errorList;
|
std::list<std::string> _errorList;
|
||||||
|
|
|
@ -74,8 +74,7 @@ private:
|
||||||
|
|
||||||
void run()
|
void run()
|
||||||
{
|
{
|
||||||
// This is commented out, because it causes a deadlock
|
TEST_CASE(deadlock_with_many_errors);
|
||||||
// TEST_CASE(deadlock_with_many_errors);
|
|
||||||
TEST_CASE(no_errors_more_files);
|
TEST_CASE(no_errors_more_files);
|
||||||
TEST_CASE(no_errors_less_files);
|
TEST_CASE(no_errors_less_files);
|
||||||
TEST_CASE(no_errors_equal_amount_files);
|
TEST_CASE(no_errors_equal_amount_files);
|
||||||
|
|
Loading…
Reference in New Issue