mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-10-16 12:21:18 +02:00
27721: rationalise initialisation of file descriptors
This commit is contained in:
parent
349b6649c3
commit
7977ce0747
4 changed files with 69 additions and 42 deletions
61
Src/compat.c
61
Src/compat.c
|
@ -187,40 +187,45 @@ zpathmax(char *dir)
|
|||
#endif /* 0 */
|
||||
|
||||
#ifdef HAVE_SYSCONF
|
||||
/* This is replaced by a macro from system.h if not HAVE_SYSCONF. *
|
||||
* 0 is returned by sysconf if _SC_OPEN_MAX is unavailable; *
|
||||
* -1 is returned on error *
|
||||
* *
|
||||
* Neither of these should happen, but resort to OPEN_MAX rather *
|
||||
* than return 0 or -1 just in case. */
|
||||
/*
|
||||
* This is replaced by a macro from system.h if not HAVE_SYSCONF.
|
||||
* 0 is returned by sysconf if _SC_OPEN_MAX is unavailable;
|
||||
* -1 is returned on error
|
||||
*
|
||||
* Neither of these should happen, but resort to OPEN_MAX rather
|
||||
* than return 0 or -1 just in case.
|
||||
*
|
||||
* We'll limit the open maximum to ZSH_INITIAL_OPEN_MAX to
|
||||
* avoid probing ridiculous numbers of file descriptors.
|
||||
*/
|
||||
|
||||
/**/
|
||||
mod_export long
|
||||
zopenmax(void)
|
||||
{
|
||||
static long openmax = 0;
|
||||
long openmax;
|
||||
|
||||
if (openmax < 1) {
|
||||
if ((openmax = sysconf(_SC_OPEN_MAX)) < 1) {
|
||||
openmax = OPEN_MAX;
|
||||
} else if (openmax > OPEN_MAX) {
|
||||
/* On some systems, "limit descriptors unlimited" or the *
|
||||
* equivalent will set openmax to a huge number. Unless *
|
||||
* there actually is a file descriptor > OPEN_MAX already *
|
||||
* open, nothing in zsh requires the true maximum, and in *
|
||||
* fact it causes inefficiency elsewhere if we report it. *
|
||||
* So, report the maximum of OPEN_MAX or the largest open *
|
||||
* descriptor (is there a better way to find that?). */
|
||||
long i, j = OPEN_MAX;
|
||||
for (i = j; i < openmax; i += (errno != EINTR)) {
|
||||
errno = 0;
|
||||
if (fcntl(i, F_GETFL, 0) < 0 &&
|
||||
(errno == EBADF || errno == EINTR))
|
||||
continue;
|
||||
j = i;
|
||||
}
|
||||
openmax = j;
|
||||
if ((openmax = sysconf(_SC_OPEN_MAX)) < 1) {
|
||||
openmax = OPEN_MAX;
|
||||
} else if (openmax > OPEN_MAX) {
|
||||
/* On some systems, "limit descriptors unlimited" or the *
|
||||
* equivalent will set openmax to a huge number. Unless *
|
||||
* there actually is a file descriptor > OPEN_MAX already *
|
||||
* open, nothing in zsh requires the true maximum, and in *
|
||||
* fact it causes inefficiency elsewhere if we report it. *
|
||||
* So, report the maximum of OPEN_MAX or the largest open *
|
||||
* descriptor (is there a better way to find that?). */
|
||||
long i, j = OPEN_MAX;
|
||||
if (openmax > ZSH_INITIAL_OPEN_MAX)
|
||||
openmax = ZSH_INITIAL_OPEN_MAX;
|
||||
for (i = j; i < openmax; i += (errno != EINTR)) {
|
||||
errno = 0;
|
||||
if (fcntl(i, F_GETFL, 0) < 0 &&
|
||||
(errno == EBADF || errno == EINTR))
|
||||
continue;
|
||||
j = i;
|
||||
}
|
||||
openmax = j;
|
||||
}
|
||||
|
||||
return (max_zsh_fd > openmax) ? max_zsh_fd : openmax;
|
||||
|
@ -771,7 +776,7 @@ mk_wcwidth(wchar_t ucs)
|
|||
|
||||
/* if we arrive here, ucs is not a combining or C0/C1 control character */
|
||||
|
||||
return 1 +
|
||||
return 1 +
|
||||
(ucs >= 0x1100 &&
|
||||
(ucs <= 0x115f || /* Hangul Jamo init. consonants */
|
||||
ucs == 0x2329 || ucs == 0x232a ||
|
||||
|
|
|
@ -1928,7 +1928,7 @@ closeallelse(struct multio *mn)
|
|||
int i, j;
|
||||
long openmax;
|
||||
|
||||
openmax = zopenmax();
|
||||
openmax = fdtable_size;
|
||||
|
||||
for (i = 0; i < openmax; i++)
|
||||
if (mn->pipe != i) {
|
||||
|
|
10
Src/system.h
10
Src/system.h
|
@ -304,16 +304,22 @@ struct timezone {
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The number of file descriptors we'll allocate initially.
|
||||
* We will reallocate later if necessary.
|
||||
*/
|
||||
#define ZSH_INITIAL_OPEN_MAX 64
|
||||
#ifndef OPEN_MAX
|
||||
# ifdef NOFILE
|
||||
# define OPEN_MAX NOFILE
|
||||
# else
|
||||
/* so we will just pick something */
|
||||
# define OPEN_MAX 64
|
||||
# define OPEN_MAX ZSH_INITIAL_OPEN_MAX
|
||||
# endif
|
||||
#endif
|
||||
#ifndef HAVE_SYSCONF
|
||||
# define zopenmax() ((long) OPEN_MAX)
|
||||
# define zopenmax() ((long) (OPEN_MAX > ZSH_INITIAL_OPEN_MAX ? \
|
||||
ZSH_INITIAL_OPEN_MAX : OPEN_MAX))
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FCNTL_H
|
||||
|
|
38
Src/utils.c
38
Src/utils.c
|
@ -1621,6 +1621,27 @@ adjustwinsize(int from)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure the fdtable is large enough for fd, and that the
|
||||
* maximum fd is set appropriately.
|
||||
*/
|
||||
static void
|
||||
check_fd_table(int fd)
|
||||
{
|
||||
if (fd <= max_zsh_fd)
|
||||
return;
|
||||
|
||||
if (fd >= fdtable_size) {
|
||||
int old_size = fdtable_size;
|
||||
while (fd >= fdtable_size)
|
||||
fdtable = zrealloc(fdtable,
|
||||
(fdtable_size *= 2)*sizeof(*fdtable));
|
||||
memset(fdtable + old_size, 0,
|
||||
(fdtable_size - old_size) * sizeof(*fdtable));
|
||||
}
|
||||
max_zsh_fd = fd;
|
||||
}
|
||||
|
||||
/* Move a fd to a place >= 10 and mark the new fd in fdtable. If the fd *
|
||||
* is already >= 10, it is not moved. If it is invalid, -1 is returned. */
|
||||
|
||||
|
@ -1644,12 +1665,7 @@ movefd(int fd)
|
|||
fd = fe;
|
||||
}
|
||||
if(fd != -1) {
|
||||
if (fd > max_zsh_fd) {
|
||||
while (fd >= fdtable_size)
|
||||
fdtable = zrealloc(fdtable,
|
||||
(fdtable_size *= 2)*sizeof(*fdtable));
|
||||
max_zsh_fd = fd;
|
||||
}
|
||||
check_fd_table(fd);
|
||||
fdtable[fd] = FDT_INTERNAL;
|
||||
}
|
||||
return fd;
|
||||
|
@ -1669,12 +1685,12 @@ redup(int x, int y)
|
|||
if(x < 0)
|
||||
zclose(y);
|
||||
else if (x != y) {
|
||||
while (y >= fdtable_size)
|
||||
fdtable = zrealloc(fdtable, (fdtable_size *= 2)*sizeof(*fdtable));
|
||||
if (dup2(x, y) == -1)
|
||||
if (dup2(x, y) == -1) {
|
||||
ret = -1;
|
||||
if ((fdtable[y] = fdtable[x]) && y > max_zsh_fd)
|
||||
max_zsh_fd = y;
|
||||
} else {
|
||||
check_fd_table(y);
|
||||
fdtable[y] = fdtable[x];
|
||||
}
|
||||
zclose(x);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue