core: Optimize fork/exec for *BSD and Solaris.

* configure.ac (closefrom): Add to ac_check_funcs.
* src/posix-io.c (_gpgme_io_spawn): Use closefrom.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2017-02-03 13:56:23 +01:00
parent 93a59070c6
commit 51bd69f216
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 37 additions and 13 deletions

View File

@ -694,7 +694,7 @@ fi
# #
# Check for getgid etc # Check for getgid etc
AC_CHECK_FUNCS(getgid getegid) AC_CHECK_FUNCS(getgid getegid closefrom)
# Replacement functions. # Replacement functions.

View File

@ -459,10 +459,9 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
/* Intermediate child to prevent zombie processes. */ /* Intermediate child to prevent zombie processes. */
if ((pid = fork ()) == 0) if ((pid = fork ()) == 0)
{ {
int max_fds = get_max_fds ();
int fd;
/* Child. */ /* Child. */
int max_fds = -1;
int fd;
int seen_stdin = 0; int seen_stdin = 0;
int seen_stdout = 0; int seen_stdout = 0;
int seen_stderr = 0; int seen_stderr = 0;
@ -470,15 +469,40 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
if (atfork) if (atfork)
atfork (atforkvalue, 0); atfork (atforkvalue, 0);
/* First close all fds which will not be inherited. */ /* First close all fds which will not be inherited. If we
for (fd = 0; fd < max_fds; fd++) * have closefrom(2) we first figure out the highest fd we
{ * do not want to close, then call closefrom, and on success
for (i = 0; fd_list[i].fd != -1; i++) * use the regular code to close all fds up to the start
if (fd_list[i].fd == fd) * point of closefrom. Note that Solaris' closefrom does
break; * not return errors. */
if (fd_list[i].fd == -1) #ifdef HAVE_CLOSEFROM
close (fd); {
} fd = -1;
for (i = 0; fd_list[i].fd != -1; i++)
if (fd_list[i].fd > fd)
fd = fd_list[i].fd;
fd++;
#ifdef __sun
closefrom (fd);
max_fds = fd;
#else /*!__sun */
while ((i = closefrom (fd)) && errno == EINTR)
;
if (!i || errno == EBADF)
max_fds = fd;
#endif /*!__sun*/
}
#endif /*HAVE_CLOSEFROM*/
if (max_fds == -1)
max_fds = get_max_fds ();
for (fd = 0; fd < max_fds; fd++)
{
for (i = 0; fd_list[i].fd != -1; i++)
if (fd_list[i].fd == fd)
break;
if (fd_list[i].fd == -1)
close (fd);
}
/* And now dup and close those to be duplicated. */ /* And now dup and close those to be duplicated. */
for (i = 0; fd_list[i].fd != -1; i++) for (i = 0; fd_list[i].fd != -1; i++)