diff options
author | Werner Koch <[email protected]> | 2017-02-03 12:56:23 +0000 |
---|---|---|
committer | Werner Koch <[email protected]> | 2017-02-03 12:56:23 +0000 |
commit | 51bd69f216a9e2930eeba4b5f6c20e952a381720 (patch) | |
tree | b3cc6bb0af9dd99cfd2573d3b387eed47a34fdea /src/posix-io.c | |
parent | core: Fix possible deadlock due to get_max_fds. (diff) | |
download | gpgme-51bd69f216a9e2930eeba4b5f6c20e952a381720.tar.gz gpgme-51bd69f216a9e2930eeba4b5f6c20e952a381720.zip |
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 <[email protected]>
Diffstat (limited to 'src/posix-io.c')
-rw-r--r-- | src/posix-io.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/src/posix-io.c b/src/posix-io.c index cabb3e50..a351806f 100644 --- a/src/posix-io.c +++ b/src/posix-io.c @@ -459,10 +459,9 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags, /* Intermediate child to prevent zombie processes. */ if ((pid = fork ()) == 0) { - int max_fds = get_max_fds (); - int fd; - /* Child. */ + int max_fds = -1; + int fd; int seen_stdin = 0; int seen_stdout = 0; int seen_stderr = 0; @@ -470,15 +469,40 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags, if (atfork) atfork (atforkvalue, 0); - /* First close all fds which will not be inherited. */ - 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); - } + /* First close all fds which will not be inherited. If we + * have closefrom(2) we first figure out the highest fd we + * do not want to close, then call closefrom, and on success + * use the regular code to close all fds up to the start + * point of closefrom. Note that Solaris' closefrom does + * not return errors. */ +#ifdef HAVE_CLOSEFROM + { + 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. */ for (i = 0; fd_list[i].fd != -1; i++) |