On Wed, Jan 30, 2019 at 02:58:44PM +0000, Clint Adams wrote: > On Wed, Jan 30, 2019 at 09:51:42AM -0500, Dan Martins wrote: > > On systems where the nofile limit is large, fakeroot hangs > > For example on an Arch Linux system, where DefaultLimitNOFILE=infinity > > in /etc/systemd/system.conf: > > Any idea how other programs are being patched to cope with this?
Here is the patch to make it use /proc/self/fd, similar to what we do in apt, and other software does. This uses dirfd to avoid closing the directory fd under us while iterating over it; an alternative can be to just not use close() but instead fcntl(fl, F_SETFD, FD_CLOEXEC) such that the fds will all be closed by the time you exec - which is the concrete approach taken in apt. You'll have to see what works better for you in terms of standard compliance; dirfd was a BSD 4.3 extension standardised only in POSIX.1-2008. /proc/self/fd itself is implemented on Linux, and I guess BSDs also have a /proc compat layer, but it's been a while since I looked into it. Neither approach of closing fds is POSIX compliant, given that the system may open and require arbitrary descriptors, but oh well, in practice it works fine, and there is no approach that is compliant :D -- debian developer - deb.li/jak | jak-linux.org - free software dev ubuntu core developer i speak de, en
Description: Optimize file descriptor closing Closing all the fds is a severe performance issue in containers when ulimit is high. We fixed that in APT a long time ago, time to apply the same fix here. Author: Julian Andres Klode <juli...@ubuntu.com> --- a/faked.c +++ b/faked.c @@ -107,6 +107,7 @@ #ifdef HAVE_SYS_XATTR_H #include <sys/xattr.h> #endif +#include <dirent.h> #include <fcntl.h> #include <ctype.h> #include <stdio.h> @@ -1502,16 +1503,32 @@ int main(int argc, char **argv){ /* literally copied from the linux klogd code, go to background */ if ((pid=fork()) == 0){ int fl; - int num_fds = getdtablesize(); + DIR *dir; - fflush(stdout); + dir = opendir("/proc/self/fd"); + if (dir != NULL) { + struct dirent *ent; + int dfd = dirfd(dir); + while (ent = readdir(dir)) { + fl = atoi(ent->d_name); + if (fl >= 0 && fl != dfd) +#ifdef FAKEROOT_FAKENET + if (fl != sd) +#endif /* FAKEROOT_FAKENET */ + close(fl); + } + closedir(dir); + } + else { + int num_fds = getdtablesize(); - /* This is the child closing its file descriptors. */ - for (fl= 0; fl <= num_fds; ++fl) + /* This is the child closing its file descriptors. */ + for (fl= 0; fl <= num_fds; ++fl) #ifdef FAKEROOT_FAKENET - if (fl != sd) + if (fl != sd) #endif /* FAKEROOT_FAKENET */ - close(fl); + close(fl); + } setsid(); } else { printf("%li:%i\n",(long)FAKE_KEY,pid);