Fixed #1650 (Cppcheck deadlock)

http://sourceforge.net/apps/trac/cppcheck/ticket/1650
This commit is contained in:
Reijo Tomperi 2010-07-07 15:42:39 +03:00
parent f5d3042635
commit b5da0b8ed2
3 changed files with 65 additions and 51 deletions

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);