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,13 +467,7 @@ static int get_highest_fd (void)
QSE_CLOSEDIR (d); QSE_CLOSEDIR (d);
return maxfd; return maxfd;
} }
#endif
#if defined(F_MAXFD)
fd = QSE_FCNTL (0, F_MAXFD, 0);
#endif
if (fd <= -1)
{
if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 || if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 ||
rlim.rlim_max == RLIM_INFINITY) rlim.rlim_max == RLIM_INFINITY)
{ {
@ -423,7 +482,7 @@ static int get_highest_fd (void)
* _SC_OPEN_MAX returnes the maximum number of file * _SC_OPEN_MAX returnes the maximum number of file
* descriptors. make adjustment */ * descriptors. make adjustment */
if (fd > 0) fd--; 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
@ -1660,6 +1721,8 @@ create_process:
qse_pio_hnd_t devnull = -1; qse_pio_hnd_t devnull = -1;
if (!(flags & QSE_PIO_NOCLOEXEC)) if (!(flags & QSE_PIO_NOCLOEXEC))
{
if (close_unneeded_fds_using_proc (handle, 6) <= -1)
{ {
int fd = get_highest_fd (); int fd = get_highest_fd ();
@ -1676,6 +1739,7 @@ create_process:
fd--; fd--;
} }
} }
}
if (flags & QSE_PIO_WRITEIN) if (flags & QSE_PIO_WRITEIN)
{ {