Bug 425

Summary: sudo-1.7.4 hogs cpu via waitpid in sudo_execve
Product: Sudo Reporter: Hugo Mildenberger <Hugo.Mildenberger>
Component: SudoAssignee: Todd C. Miller <Todd.Miller>
Status: RESOLVED FIXED    
Severity: normal    
Priority: high    
Version: 1.7.4   
Hardware: All   
OS: Linux   
URL: http://bugs.gentoo.org/show_bug.cgi?id=331651

Description Hugo Mildenberger 2010-08-09 05:08:13 MDT
sudo eats up >90% of the CPU time while waiting for a child in exec. htop s revealed that sudo continuosly calls waitpid(somepid, someaddress,WNOHANG|WSTOPPED) = 0.

There is logic error in sudo-1.7.4/exec.c which actually causes this misbehaviour:

257             do {
258 #ifdef sudo_waitpid
259                 pid = sudo_waitpid(child, &status, WUNTRACED|WNOHANG);
260 #else
261                 pid = wait(&status);
262 #endif
263                 if (pid == child) {
264                     if (!log_io) {
265                         if (WIFSTOPPED(status)) {
266                             /* Child may not have privs to suspend us
itself. */
267                             kill(getpid(), WSTOPSIG(status));
268                         } else {
269                             /* Child has exited, we are done. */
270                             cstat->type = CMD_WSTATUS;
271                             cstat->val = status;
272                             return 0;
273                         }
274                     }
275                     /* Else we get ECONNRESET on sv[0] if child dies. */
276                 }
277             } while (pid != -1 || errno == EINTR);

Line 277 should read:

277             } while (pid == -1 && errno == EINTR);

and should probably also move up to line 263

sudo-1.7.2_p7 and sudo-1.7.3 appear also to be affected by this, one way or another. Look into sudo_edit.c instead of exec.c or do a "grep EINTR *.c"

The latest version of exec.c in VCS alread has the do-while condition correct.
Comment 1 Todd C. Miller 2010-08-09 08:39:10 MDT
Fixed in sudo 1.7.4p2, available now.