enhanced qse_pio_t to use /proc/self/fd and/or /proc/<<pid>>/fd more actively

This commit is contained in:
hyung-hwan 2014-09-17 15:02:14 +00:00
parent bb7ece059d
commit bf25f92704

View File

@ -362,14 +362,8 @@ static QSE_INLINE int is_fd_valid_and_nocloexec (int fd)
return !(flags & FD_CLOEXEC)? 1: 0; return !(flags & FD_CLOEXEC)? 1: 0;
} }
static int get_highest_fd (void) static int close_unneeded_fds_using_proc (int* excepts, qse_size_t count)
{ {
/* TODO: consider if reading from /proc/self/fd is
* a better idea. */
struct rlimit rlim;
int fd = -1;
#if defined(__linux__)
QSE_DIR* d; QSE_DIR* d;
/* will getting the highest file descriptor be faster than /* will getting the highest file descriptor be faster than
@ -377,6 +371,77 @@ static int get_highest_fd (void)
* system limit? */ * system limit? */
d = QSE_OPENDIR (QSE_MT("/proc/self/fd")); d = QSE_OPENDIR (QSE_MT("/proc/self/fd"));
if (!d)
{
qse_mchar_t buf[64];
qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID());
d = QSE_OPENDIR (buf);
}
/* TODO: try /dev/fd - FreeBSD, Darwin, OS X*/
if (d)
{
qse_dirent_t* de;
while ((de = QSE_READDIR (d)))
{
qse_long_t l;
const qse_mchar_t* endptr;
if (de->d_name[0] == QSE_MT('.')) continue;
QSE_MBSTONUM (l, de->d_name, &endptr, 10);
if (*endptr == QSE_MT('\0'))
{
int fd = (int)l;
if ((qse_long_t)fd == l && fd != QSE_DIRFD(d) && fd > 2)
{
qse_size_t i;
for (i = 0; i < count; i++)
{
if (fd == excepts[i]) goto skip_close;
}
QSE_CLOSE (fd);
skip_close:
;
}
}
}
QSE_CLOSEDIR (d);
return 0;
}
return -1;
}
static int get_highest_fd (void)
{
struct rlimit rlim;
int fd;
QSE_DIR* d;
#if defined(F_MAXFD)
fd = QSE_FCNTL (0, F_MAXFD, 0);
if (fd >= 0) return fd;
#endif
/* will getting the highest file descriptor be faster than
* attempting to close any files descriptors less than the
* system limit? */
d = QSE_OPENDIR (QSE_MT("/proc/self/fd"));
if (!d)
{
qse_mchar_t buf[64];
qse_mbsxfmt (buf, QSE_COUNTOF(buf), QSE_MT("/proc/%d/fd"), QSE_GETPID());
d = QSE_OPENDIR (buf);
}
/* TODO: try /dev/fd - FreeBSD, Darwin, OS X*/
if (d) if (d)
{ {
int maxfd = -1; int maxfd = -1;
@ -402,28 +467,22 @@ static int get_highest_fd (void)
QSE_CLOSEDIR (d); QSE_CLOSEDIR (d);
return maxfd; return maxfd;
} }
#endif
#if defined(F_MAXFD) if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 ||
fd = QSE_FCNTL (0, F_MAXFD, 0); rlim.rlim_max == RLIM_INFINITY)
#endif
if (fd <= -1)
{ {
if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 || #if defined(HAVE_SYSCONF)
rlim.rlim_max == RLIM_INFINITY) fd = sysconf (_SC_OPEN_MAX);
{ #endif
#if defined(HAVE_SYSCONF)
fd = sysconf (_SC_OPEN_MAX);
#endif
}
else fd = rlim.rlim_max;
if (fd == -1) fd = 1024; /* fallback */
/* F_MAXFD is the highest fd. but RLIMIT_NOFILE and
* _SC_OPEN_MAX returnes the maximum number of file
* descriptors. make adjustment */
if (fd > 0) fd--;
} }
else fd = rlim.rlim_max;
if (fd == -1) fd = 1024; /* fallback */
/* F_MAXFD is the highest fd. but RLIMIT_NOFILE and
* _SC_OPEN_MAX returnes the maximum number of file
* descriptors. make adjustment */
if (fd > 0) fd--;
return fd; return fd;
} }
@ -1469,6 +1528,8 @@ create_process:
if (!(flags & QSE_PIO_NOCLOEXEC)) if (!(flags & QSE_PIO_NOCLOEXEC))
{ {
/* cannot call close_unneeded_fds_using_proc() in the vfork() context */
int fd = highest_fd; int fd = highest_fd;
/* close all other unknown open handles except /* close all other unknown open handles except
@ -1661,19 +1722,22 @@ create_process:
if (!(flags & QSE_PIO_NOCLOEXEC)) if (!(flags & QSE_PIO_NOCLOEXEC))
{ {
int fd = get_highest_fd (); if (close_unneeded_fds_using_proc (handle, 6) <= -1)
/* close all other unknown open handles except
* stdin/out/err and the pipes. */
while (fd > 2)
{ {
if (fd != handle[0] && fd != handle[1] && int fd = get_highest_fd ();
fd != handle[2] && fd != handle[3] &&
fd != handle[4] && fd != handle[5]) /* close all other unknown open handles except
* stdin/out/err and the pipes. */
while (fd > 2)
{ {
QSE_CLOSE (fd); if (fd != handle[0] && fd != handle[1] &&
fd != handle[2] && fd != handle[3] &&
fd != handle[4] && fd != handle[5])
{
QSE_CLOSE (fd);
}
fd--;
} }
fd--;
} }
} }