@@ -35,7 +35,7 @@ ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, Settin
3535 : _filenames(filenames), _settings(settings), _errorLogger(errorLogger), _fileCount(0 )
3636{
3737#ifdef THREADING_MODEL_FORK
38- _pipe[ 0 ] = _pipe[ 1 ] = 0 ;
38+ _wpipe = 0 ;
3939#endif
4040}
4141
@@ -55,10 +55,10 @@ void ThreadExecutor::addFileContent(const std::string &path, const std::string &
5555
5656#ifdef THREADING_MODEL_FORK
5757
58- int ThreadExecutor::handleRead (unsigned int &result)
58+ int ThreadExecutor::handleRead (int rpipe, unsigned int &result)
5959{
6060 char type = 0 ;
61- if (read (_pipe[ 0 ] , &type, 1 ) <= 0 )
61+ if (read (rpipe , &type, 1 ) <= 0 )
6262 {
6363 if (errno == EAGAIN )
6464 return 0 ;
@@ -73,14 +73,14 @@ int ThreadExecutor::handleRead(unsigned int &result)
7373 }
7474
7575 unsigned int len = 0 ;
76- if (read (_pipe[ 0 ] , &len, sizeof (len)) <= 0 )
76+ if (read (rpipe , &len, sizeof (len)) <= 0 )
7777 {
7878 std::cerr << " #### You found a bug from cppcheck.\n ThreadExecutor::handleRead error, type was:" << type << std::endl;
7979 exit (0 );
8080 }
8181
8282 char *buf = new char [len];
83- if (read (_pipe[ 0 ] , buf, len) <= 0 )
83+ if (read (rpipe , buf, len) <= 0 )
8484 {
8585 std::cerr << " #### You found a bug from cppcheck.\n ThreadExecutor::handleRead error, type was:" << type << std::endl;
8686 exit (0 );
@@ -134,32 +134,35 @@ unsigned int ThreadExecutor::check()
134134{
135135 _fileCount = 0 ;
136136 unsigned int result = 0 ;
137- if (pipe (_pipe) == -1 )
138- {
139- perror (" pipe" );
140- exit (1 );
141- }
142-
143- int flags = 0 ;
144- if ((flags = fcntl (_pipe[0 ], F_GETFL , 0 )) < 0 )
145- {
146- perror (" fcntl" );
147- exit (1 );
148- }
149-
150- if (fcntl (_pipe[0 ], F_SETFL , flags | O_NONBLOCK ) < 0 )
151- {
152- perror (" fcntl" );
153- exit (1 );
154- }
155137
156- unsigned int childCount = 0 ;
138+ std::list<int > rpipes;
139+ std::map<pid_t , std::string> childFile;
157140 unsigned int i = 0 ;
158141 while (true )
159142 {
160143 // Start a new child
161- if (i < _filenames.size () && childCount < _settings._jobs )
144+ if (i < _filenames.size () && rpipes. size () < _settings._jobs )
162145 {
146+ int pipes[2 ];
147+ if (pipe (pipes) == -1 )
148+ {
149+ perror (" pipe" );
150+ exit (1 );
151+ }
152+
153+ int flags = 0 ;
154+ if ((flags = fcntl (pipes[0 ], F_GETFL , 0 )) < 0 )
155+ {
156+ perror (" fcntl" );
157+ exit (1 );
158+ }
159+
160+ if (fcntl (pipes[0 ], F_SETFL , flags | O_NONBLOCK ) < 0 )
161+ {
162+ perror (" fcntl" );
163+ exit (1 );
164+ }
165+
163166 pid_t pid = fork ();
164167 if (pid < 0 )
165168 {
@@ -169,6 +172,9 @@ unsigned int ThreadExecutor::check()
169172 }
170173 else if (pid == 0 )
171174 {
175+ close (pipes[0 ]);
176+ _wpipe = pipes[1 ];
177+
172178 CppCheck fileChecker (*this , false );
173179 fileChecker.settings (_settings);
174180
@@ -190,31 +196,70 @@ unsigned int ThreadExecutor::check()
190196 exit (0 );
191197 }
192198
193- ++childCount;
199+ close (pipes[1 ]);
200+ rpipes.push_back (pipes[0 ]);
201+ childFile[pid] = _filenames[i];
202+
194203 ++i;
195204 }
196- else if (childCount > 0 )
205+ else if (!rpipes. empty () )
197206 {
198- // Wait for child to quit before stating new processes
199- while (true )
207+ fd_set rfds;
208+ FD_ZERO (&rfds);
209+ for (std::list<int >::const_iterator rp = rpipes.begin (); rp != rpipes.end (); ++rp)
210+ FD_SET (*rp, &rfds);
211+
212+ int r = select (*std::max_element (rpipes.begin (), rpipes.end ()) + 1 , &rfds, NULL , NULL , NULL );
213+
214+ if (r > 0 )
200215 {
201- int readRes = handleRead (result);
202- if (readRes == -1 )
203- break ;
204- else if (readRes == 0 )
216+ std::list<int >::iterator rp = rpipes.begin ();
217+ while (rp != rpipes.end ())
205218 {
206- struct timespec duration;
207- duration.tv_sec = 0 ;
208- duration.tv_nsec = 5 * 1000 * 1000 ; // 5 ms
209- nanosleep (&duration, NULL );
219+ if (FD_ISSET (*rp, &rfds))
220+ {
221+ int readRes = handleRead (*rp, result);
222+ if (readRes == -1 )
223+ {
224+ close (*rp);
225+ rp = rpipes.erase (rp);
226+ }
227+ else
228+ ++rp;
229+ }
230+ else
231+ ++rp;
210232 }
211233 }
212234
213235 int stat = 0 ;
214- waitpid (0 , &stat, 0 );
215- --childCount;
236+ pid_t child = waitpid (0 , &stat, WNOHANG );
237+ if (child > 0 )
238+ {
239+ std::string childname;
240+ std::map<pid_t , std::string>::iterator c = childFile.find (child);
241+ if (c != childFile.end ())
242+ {
243+ childname = c->second ;
244+ childFile.erase (c);
245+ }
246+
247+ if (WIFSIGNALED (stat))
248+ {
249+ std::ostringstream oss;
250+ oss << " Internal error: Child process crashed with signal " << WTERMSIG (stat);
251+
252+ std::list<ErrorLogger::ErrorMessage::FileLocation> locations;
253+ locations.push_back (ErrorLogger::ErrorMessage::FileLocation (childname, 0 ));
254+ const ErrorLogger::ErrorMessage errmsg (locations,
255+ Severity::error,
256+ oss.str (),
257+ " cppcheckError" );
258+ _errorLogger.reportErr (errmsg);
259+ }
260+ }
216261 }
217- else if (childCount == 0 )
262+ else
218263 {
219264 // All done
220265 break ;
@@ -232,7 +277,7 @@ void ThreadExecutor::writeToPipe(char type, const std::string &data)
232277 out[0 ] = type;
233278 std::memcpy (&(out[1 ]), &len, sizeof (len));
234279 std::memcpy (&(out[1 +sizeof (len)]), data.c_str (), len);
235- if (write (_pipe[ 1 ] , out, len + 1 + sizeof (len)) <= 0 )
280+ if (write (_wpipe , out, len + 1 + sizeof (len)) <= 0 )
236281 {
237282 delete [] out;
238283 out = 0 ;
0 commit comments