This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/15020] New: wordexp goes into busy loop after child process closes it's output file descriptor


http://sourceware.org/bugzilla/show_bug.cgi?id=15020

             Bug #: 15020
           Summary: wordexp goes into busy loop after child process closes
                    it's output file descriptor
           Product: glibc
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: unassigned@sourceware.org
        ReportedBy: ujvari@microsec.hu
                CC: drepper.fsp@gmail.com
    Classification: Unclassified


When wordexp is used to execute shell command and run a program in that command
the program may close it's output file descriptor before exits. The wordexp
function reads the program output (from the read side of a pipe), but when the
program closes it output file descriptor (the write side of a pipe), the
wrodexp function goes into a busy loop.

An strace output when a program uses wordexp and goes into busy loop:

> 15:44:38.748956 pipe([5, 8])            = 0 <0.000016>
> 15:44:38.749027 clone(Process 20369 attached
> child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x42292b48) = 20369 <0.001831>
> [pid 30525] 15:44:38.750969 close(8 <unfinished ...>
> [pid 20369] 15:44:38.751074 dup2(8, 1 <unfinished ...>
> [pid 30525] 15:44:38.751098 <... close resumed> ) = 0 <0.000096>
> [pid 20369] 15:44:38.751127 <... dup2 resumed> ) = 1 <0.000035>
> [pid 30525] 15:44:38.751150 read(5,  <unfinished ...>
> [pid 20369] 15:44:38.751180 close(8)    = 0 <0.000008>
> [pid 20369] 15:44:38.751216 close(2)    = 0 <0.000035>
> [pid 20369] 15:44:38.751285 open("/dev/null", O_WRONLY) = 2 <0.000018>
> [pid 20369] 15:44:38.751347 fstat64(2, {st_mode=S_IFCHR|0666, st_rdev=makedev(1, 3), ...}) = 0 <0.000008>
> [pid 20369] 15:44:38.751437 close(5)    = 0 <0.000007>
> [pid 20369] 15:44:38.751477 execve("/bin/sh", ["/bin/sh", "-c", "/usr/bin/stat -c %s /tmp/med30525f000000"], [/* 122 vars */]) = 0 <0.001610>
> ...
> [pid 20369] 15:44:38.826332 write(1, "11486\n", 6 <unfinished ...>
> [pid 30525] 15:44:38.826473 <... read resumed> "11486\n", 128) = 6 <0.075257>
> [pid 20369] 15:44:38.826578 <... write resumed> ) = 6 <0.000173>
> [pid 30525] 15:44:38.826661 read(5,  <unfinished ...>
> [pid 20369] 15:44:38.826773 close(1 <unfinished ...>
> [pid 30525] 15:44:38.826881 <... read resumed> "", 128) = 0 <0.000121>
> [pid 20369] 15:44:38.826962 <... close resumed> ) = 0 <0.000129>
> [pid 30525] 15:44:38.827037 waitpid(20369, 0xbffecfc0, WNOHANG) = 0 <0.000008>
> [pid 30525] 15:44:38.827182 read(5, "", 128) = 0 <0.000007>
> [pid 30525] 15:44:38.827311 waitpid(20369, 0xbffecfc0, WNOHANG) = 0 <0.000008>
> [pid 30525] 15:44:38.827431 read(5, "", 128) = 0 <0.000008>
> ...
> [pid 30525] 15:44:38.997549 read(5, "", 128) = 0 <0.000007>
> [pid 30525] 15:44:38.997586 waitpid(20369, 0xbffecfc0, WNOHANG) = 0 <0.000007>
> [pid 30525] 15:44:38.997624 read(5, "", 128) = 0 <0.000007>
> [pid 30525] 15:44:38.997661 waitpid(20369, 0xbffecfc0, WNOHANG) = 0 <0.000007>
> [pid 30525] 15:44:38.997699 read(5, "", 128) = 0 <0.000007>
> [pid 30525] 15:44:38.997737 waitpid(20369,  <unfinished ...>
> [pid 20369] 15:44:38.997777 <... munmap resumed> ) = 0 <0.131820>
> [pid 30525] 15:44:38.997826 <... waitpid resumed> 0xbffecfc0, WNOHANG) = 0 <0.000072>
> [pid 20369] 15:44:38.997854 exit_group(0) = ?
Process 20369 detached
> 15:44:38.997986 read(5, "", 128)        = 0 <0.000007>
> 15:44:38.998026 waitpid(20369, 0xbffecfc0, WNOHANG) = -1 ECHILD (No child processes) <0.000007>
> 15:44:38.998070 read(5, "", 128)        = 0 <0.000006>
> 15:44:38.998105 close(5)                = 0 <0.000013>

The corresponding wordexp code:

>  951       while (1)
>  952         {
>  953           if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
>  954                                                     bufsize))) < 1)
>  955             {
>  956               if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, WNOHANG)) == 0)
>  957                 continue;
>  958               if ((buflen = TEMP_FAILURE_RETRY (__read (fildes[0], buffer,
>  959                                                         bufsize))) < 1)
>  960                 break;
>  961             }
>  ...
>  968         }
(This code snippet is duplicated at lines 981-991.)

Wordexp code tries to read from the pipe when it's write side already closed.
On the closed pipe the read function does not block, but immediately returns
with 0 as the read file handle is already at EOF. Then waitpid is called while
the child process has not exited yet, therefore it returns with 0. This loop
goes on till the child process has really exited and waitpid returns its PID.

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]