Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I../bash -I../bash/include -I../bash/lib -g -O2 -Wall uname output: Linux system76-pc 2.6.28-18-generic #59-Ubuntu SMP Thu Jan 28 01:40:19 UTC 2010 x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu
Bash Version: 3.2 Patch Level: 48 Release Status: release Description: Bash seems to be opening unnamed pipes for use in tab completion, but not closing them. These pipes are then also not closed across execve. Repeat-By: The easiest way to demonstrate this (and how I accidentally found it) is to: $ ls -l /proc/self/fd\t\t Where \t\t is double tab press to trigger tab completion suggestions. If you press [enter] here you will not that ls (which is now self in /proc) has several unnamed pipes open, which it has retained from before execve made it ls rather than bash. After ls has exited running the command again without the double tab suggestions will yield no unnamed pipes. If you do: $ ls -l /proc/self/fd\t\t 0 1 2 255 3 61 62 63 \t 0 1 2 255 3 59 60 61 62 63 \t 0 1 2 255 3 57 58 59 60 61 62 63 That is, after the initial tab completion suggestion (triggered by the double tab) you continue to press the tab key it will continue to make more unnamed pipes. The \t\t seems to generate 3 unnamed pipes [61 62 63], and each additional \t generates 2 additional pipes, numbered down from 64-1. The extra tab from the \t\t is probably because the first \t opens one for doing full tab completion while the additional \t is interpreted as give me suggestions, which uses two pipes. In both instances the pipes are obviously not closed and are retained across execve. Continuing to press \t will cause the list to keep growing by 2 each time until bash starts asking if you want it to display 100 possibilities. If you keep going after this bash will eventually die (probably because of failure when attempting to open more pipes). Fix: Close those pipes when bash is through with them. You may also consider using the O_CLOEXEC flag and and pipe2 followed by a fcntl in children after forks to clear the FD_CLOEXEC flag as an additional guard against unintentional sharing of file descriptors across execve.