Skip to content

Commit b5da0b8

Browse files
committed
1 parent f5d3042 commit b5da0b8

3 files changed

Lines changed: 65 additions & 51 deletions

File tree

cli/threadexecutor.cpp

Lines changed: 57 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <cstdlib>
2828
#include <cstring>
2929
#include <cstdio>
30+
#include <errno.h>
3031
#endif
3132

3233
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 &
5152

5253
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
5354

54-
bool ThreadExecutor::handleRead(unsigned int &result)
55+
int ThreadExecutor::handleRead(unsigned int &result)
5556
{
5657
char type = 0;
5758
if (read(_pipe[0], &type, 1) <= 0)
5859
{
59-
return false;
60+
if( errno == EAGAIN )
61+
return 0;
62+
63+
return -1;
6064
}
6165

6266
if (type != '1' && type != '2' && type != '3')
@@ -104,10 +108,12 @@ bool ThreadExecutor::handleRead(unsigned int &result)
104108
iss >> fileResult;
105109
result += fileResult;
106110
_errorLogger.reportStatus(_fileCount, _filenames.size());
111+
delete [] buf;
112+
return -1;
107113
}
108114

109115
delete [] buf;
110-
return true;
116+
return 1;
111117
}
112118

113119
unsigned int ThreadExecutor::check()
@@ -134,65 +140,68 @@ unsigned int ThreadExecutor::check()
134140
}
135141

136142
unsigned int childCount = 0;
137-
for (unsigned int i = 0; i < _filenames.size(); i++)
143+
unsigned int i = 0;
144+
while( true )
138145
{
139-
// Keep only wanted amount of child processes running at a time.
140-
if (childCount >= _settings._jobs)
146+
// Start a new child
147+
if( i < _filenames.size() && childCount < _settings._jobs )
141148
{
142-
while (handleRead(result))
149+
pid_t pid = fork();
150+
if (pid < 0)
151+
{
152+
// Error
153+
std::cerr << "Failed to create child process" << std::endl;
154+
exit(EXIT_FAILURE);
155+
}
156+
else if (pid == 0)
143157
{
158+
CppCheck fileChecker(*this);
159+
fileChecker.settings(_settings);
160+
161+
if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end())
162+
{
163+
// File content was given as a string
164+
fileChecker.addFile(_filenames[i], _fileContents[ _filenames[i] ]);
165+
}
166+
else
167+
{
168+
// Read file from a file
169+
fileChecker.addFile(_filenames[i]);
170+
}
171+
172+
unsigned int resultOfCheck = fileChecker.check();
173+
std::ostringstream oss;
174+
oss << resultOfCheck;
175+
writeToPipe('3', oss.str());
176+
exit(0);
177+
}
144178

179+
++childCount;
180+
++i;
181+
}
182+
else if (childCount > 0)
183+
{
184+
// Wait for child to quit before stating new processes
185+
while(true)
186+
{
187+
int readRes = handleRead(result);
188+
if( readRes == -1 )
189+
break;
190+
else if( readRes == 0 )
191+
usleep(5000); // 5 ms
145192
}
146193

147194
int stat = 0;
148195
waitpid(0, &stat, 0);
149196
--childCount;
150197
}
151-
152-
pid_t pid = fork();
153-
if (pid < 0)
198+
else if(childCount == 0)
154199
{
155-
// Error
156-
std::cerr << "Failed to create child process" << std::endl;
157-
exit(EXIT_FAILURE);
200+
// All done
201+
break;
158202
}
159-
else if (pid == 0)
160-
{
161-
CppCheck fileChecker(*this);
162-
fileChecker.settings(_settings);
163-
164-
if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end())
165-
{
166-
// File content was given as a string
167-
fileChecker.addFile(_filenames[i], _fileContents[ _filenames[i] ]);
168-
}
169-
else
170-
{
171-
// Read file from a file
172-
fileChecker.addFile(_filenames[i]);
173-
}
174-
175-
unsigned int resultOfCheck = fileChecker.check();
176-
std::ostringstream oss;
177-
oss << resultOfCheck;
178-
writeToPipe('3', oss.str());
179-
exit(0);
180-
}
181-
182-
++childCount;
183203
}
184204

185-
while (childCount > 0)
186-
{
187-
int stat = 0;
188-
waitpid(0, &stat, 0);
189-
--childCount;
190-
}
191-
192-
while (handleRead(result))
193-
{
194-
195-
}
196205

197206
return result;
198207
}

cli/threadexecutor.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,13 @@ class ThreadExecutor : public ErrorLogger
5858

5959
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
6060
private:
61-
bool handleRead(unsigned int &result);
61+
/**
62+
* Read from the pipe, parse and handle what ever is in there.
63+
*@return -1 in case of error
64+
* 0 if there is nothing in the pipe to be read
65+
* 1 if we did read something
66+
*/
67+
int handleRead(unsigned int &result);
6268
void writeToPipe(char type, const std::string &data);
6369
int _pipe[2];
6470
std::list<std::string> _errorList;

test/testthreadexecutor.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,7 @@ class TestThreadExecutor : public TestFixture
7474

7575
void run()
7676
{
77-
// This is commented out, because it causes a deadlock
78-
// TEST_CASE(deadlock_with_many_errors);
77+
TEST_CASE(deadlock_with_many_errors);
7978
TEST_CASE(no_errors_more_files);
8079
TEST_CASE(no_errors_less_files);
8180
TEST_CASE(no_errors_equal_amount_files);

0 commit comments

Comments
 (0)