enhanced get_highest_fd().
fixed an inifite looping bug in pio with posix_spawn() used
This commit is contained in:
parent
04e6df3dd8
commit
822bcf3afb
@ -71,7 +71,7 @@ struct qse_dir_t
|
||||
#elif defined(__DOS__)
|
||||
struct find_t f;
|
||||
#else
|
||||
DIR* dp;
|
||||
QSE_DIR* dp;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -351,12 +351,12 @@ static int assert_executable (qse_pio_t* pio, const qse_mchar_t* path)
|
||||
|
||||
static QSE_INLINE int is_fd_valid (int fd)
|
||||
{
|
||||
return fcntl (fd, F_GETFD) != -1 || errno != EBADF;
|
||||
return QSE_FCNTL (fd, F_GETFD, 0) != -1 || errno != EBADF;
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_fd_valid_and_nocloexec (int fd)
|
||||
{
|
||||
int flags = fcntl (fd, F_GETFD);
|
||||
int flags = QSE_FCNTL (fd, F_GETFD, 0);
|
||||
if (flags == -1)
|
||||
{
|
||||
if (errno == EBADF) return 0; /* invalid. return false */
|
||||
@ -372,10 +372,45 @@ static int get_highest_fd (void)
|
||||
struct rlimit rlim;
|
||||
int fd = -1;
|
||||
|
||||
#if defined(F_MAXFD)
|
||||
fd = fcntl (0, F_MAXFD);
|
||||
#if defined(__linux__)
|
||||
QSE_DIR* d;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
int maxfd = -1;
|
||||
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'))
|
||||
{
|
||||
fd = (int)l;
|
||||
if ((qse_long_t)fd == l && fd != QSE_DIRFD(d))
|
||||
{
|
||||
if (fd > maxfd) maxfd = fd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QSE_CLOSEDIR (d);
|
||||
return maxfd;
|
||||
}
|
||||
#endif
|
||||
if (fd == -1)
|
||||
|
||||
#if defined(F_MAXFD)
|
||||
fd = QSE_FCNTL (0, F_MAXFD, 0);
|
||||
#endif
|
||||
if (fd <= -1)
|
||||
{
|
||||
if (QSE_GETRLIMIT (RLIMIT_NOFILE, &rlim) <= -1 ||
|
||||
rlim.rlim_max == RLIM_INFINITY)
|
||||
@ -1271,19 +1306,20 @@ create_process:
|
||||
int fd = get_highest_fd ();
|
||||
while (fd > 2)
|
||||
{
|
||||
if (fd == handle[0] || fd == handle[1] ||
|
||||
fd == handle[2] || fd == handle[3] ||
|
||||
fd == handle[4] || fd == handle[5]) continue;
|
||||
|
||||
/* closing attempt on a best-effort basis.
|
||||
* posix_spawn() fails if the file descriptor added
|
||||
* with addclose() is closed before posix_spawn().
|
||||
* addclose() if no FD_CLOEXEC is set or it's unknown. */
|
||||
if (is_fd_valid_and_nocloexec(fd) &&
|
||||
(pserr = posix_spawn_file_actions_addclose (&fa, fd)) != 0)
|
||||
if (fd != handle[0] && fd != handle[1] &&
|
||||
fd != handle[2] && fd != handle[3] &&
|
||||
fd != handle[4] && fd != handle[5])
|
||||
{
|
||||
pio->errnum = syserr_to_errnum (pserr);
|
||||
goto oops;
|
||||
/* closing attempt on a best-effort basis.
|
||||
* posix_spawn() fails if the file descriptor added
|
||||
* with addclose() is closed before posix_spawn().
|
||||
* addclose() if no FD_CLOEXEC is set or it's unknown. */
|
||||
if (is_fd_valid_and_nocloexec(fd) &&
|
||||
(pserr = posix_spawn_file_actions_addclose (&fa, fd)) != 0)
|
||||
{
|
||||
pio->errnum = syserr_to_errnum (pserr);
|
||||
goto oops;
|
||||
}
|
||||
}
|
||||
fd--;
|
||||
}
|
||||
@ -1398,8 +1434,7 @@ create_process:
|
||||
/* prepare some data before vforking for vfork limitation.
|
||||
* the child in vfork should not make function calls or
|
||||
* change data shared with the parent. */
|
||||
if (!(flags & QSE_PIO_NOCLOEXEC))
|
||||
highest_fd = get_highest_fd ();
|
||||
if (!(flags & QSE_PIO_NOCLOEXEC)) highest_fd = get_highest_fd ();
|
||||
envarr = env? qse_env_getarr(env): environ;
|
||||
|
||||
QSE_SYSCALL0 (pid, SYS_vfork);
|
||||
|
@ -372,6 +372,8 @@
|
||||
#define QSE_OPENDIR(name) opendir(name)
|
||||
#define QSE_CLOSEDIR(dir) closedir(dir)
|
||||
#define QSE_REWINDDIR(dir) rewinddir(dir)
|
||||
#define QSE_DIRFD(dir) dirfd(dir)
|
||||
#define QSE_DIR DIR
|
||||
|
||||
#if defined(HAVE_READDIR64)
|
||||
typedef struct dirent64 qse_dirent_t;
|
||||
|
Loading…
x
Reference in New Issue
Block a user