common: Cope with AIX problem on number of open files.

* common/exechelp.c: Limit returned value for too hight values.
--

GnuPG-bug-id: 1778

(backport from master commit 987532b038)

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2016-01-15 15:32:18 +01:00
parent baae8d50d7
commit 776bee6d37
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 48 additions and 38 deletions

View File

@ -21,11 +21,14 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_STDINT_H
# include <stdint.h>
#endif
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <assert.h> #include <assert.h>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */ #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth. */
@ -33,7 +36,7 @@
#undef USE_GNU_PTH #undef USE_GNU_PTH
#endif #endif
#ifdef USE_GNU_PTH #ifdef USE_GNU_PTH
#include <pth.h> #include <pth.h>
#endif #endif
#ifndef HAVE_W32_SYSTEM #ifndef HAVE_W32_SYSTEM
@ -63,7 +66,7 @@
and some are not. However we want to use pth_fork and pth_waitpid and some are not. However we want to use pth_fork and pth_waitpid
here. Using a weak symbol works but is not portable - we should here. Using a weak symbol works but is not portable - we should
provide a an explicit dummy pth module instead of using the provide a an explicit dummy pth module instead of using the
pragma. */ pragma. */
#ifndef _WIN32 #ifndef _WIN32
#pragma weak pth_fork #pragma weak pth_fork
#pragma weak pth_waitpid #pragma weak pth_waitpid
@ -134,6 +137,13 @@ get_max_fds (void)
if (max_fds == -1) if (max_fds == -1)
max_fds = 256; /* Arbitrary limit. */ max_fds = 256; /* Arbitrary limit. */
/* AIX returns INT32_MAX instead of a proper value. We assume that
this is always an error and use an arbitrary limit. */
#ifdef INT32_MAX
if (max_fds == INT32_MAX)
max_fds = 256;
#endif
return max_fds; return max_fds;
} }
@ -202,7 +212,7 @@ get_all_open_fds (void)
array = calloc (narray, sizeof *array); array = calloc (narray, sizeof *array);
if (!array) if (!array)
return NULL; return NULL;
/* Note: The list we return is ordered. */ /* Note: The list we return is ordered. */
for (idx=0, fd=0; fd < max_fd; fd++) for (idx=0, fd=0; fd < max_fd; fd++)
if (!(fstat (fd, &statbuf) == -1 && errno == EBADF)) if (!(fstat (fd, &statbuf) == -1 && errno == EBADF))
@ -261,7 +271,7 @@ build_w32_commandline_copy (char *buffer, const char *string)
/* Build a command line for use with W32's CreateProcess. On success /* Build a command line for use with W32's CreateProcess. On success
CMDLINE gets the address of a newly allocated string. */ CMDLINE gets the address of a newly allocated string. */
static gpg_error_t static gpg_error_t
build_w32_commandline (const char *pgmname, const char * const *argv, build_w32_commandline (const char *pgmname, const char * const *argv,
char **cmdline) char **cmdline)
{ {
int i, n; int i, n;
@ -289,7 +299,7 @@ build_w32_commandline (const char *pgmname, const char * const *argv,
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
p = build_w32_commandline_copy (p, pgmname); p = build_w32_commandline_copy (p, pgmname);
for (i=0; argv[i]; i++) for (i=0; argv[i]; i++)
{ {
*p++ = ' '; *p++ = ' ';
p = build_w32_commandline_copy (p, argv[i]); p = build_w32_commandline_copy (p, argv[i]);
@ -312,7 +322,7 @@ create_inheritable_pipe (int filedes[2])
memset (&sec_attr, 0, sizeof sec_attr ); memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr; sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE; sec_attr.bInheritHandle = FALSE;
if (!CreatePipe (&r, &w, &sec_attr, 0)) if (!CreatePipe (&r, &w, &sec_attr, 0))
return -1; return -1;
@ -404,7 +414,7 @@ do_exec (const char *pgmname, const char *argv[],
/* Close all other files. */ /* Close all other files. */
close_all_fds (3, NULL); close_all_fds (3, NULL);
if (preexec) if (preexec)
preexec (); preexec ();
execv (pgmname, arg_list); execv (pgmname, arg_list);
@ -433,7 +443,7 @@ gnupg_create_inbound_pipe (int filedes[2])
log_error ("failed to translate osfhandle %p\n", (void*)fds[0]); log_error ("failed to translate osfhandle %p\n", (void*)fds[0]);
CloseHandle (fd_to_handle (fds[1])); CloseHandle (fd_to_handle (fds[1]));
} }
else else
{ {
filedes[1] = _open_osfhandle (fds[1], 1); filedes[1] = _open_osfhandle (fds[1], 1);
if (filedes[1] == -1) if (filedes[1] == -1)
@ -472,7 +482,7 @@ gnupg_create_inbound_pipe (int filedes[2])
This flag is only useful under W32 systems, so that no new This flag is only useful under W32 systems, so that no new
console is created and pops up a console window when console is created and pops up a console window when
starting the server starting the server
Bit 6: On W32 run AllowSetForegroundWindow for the child. Due to Bit 6: On W32 run AllowSetForegroundWindow for the child. Due to
error problems this actually allows SetForegroundWindow for error problems this actually allows SetForegroundWindow for
childs of this process. childs of this process.
@ -487,7 +497,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
gpg_error_t err; gpg_error_t err;
SECURITY_ATTRIBUTES sec_attr; SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi = PROCESS_INFORMATION pi =
{ {
NULL, /* Returns process handle. */ NULL, /* Returns process handle. */
0, /* Returns primary thread handle. */ 0, /* Returns primary thread handle. */
@ -515,11 +525,11 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
memset (&sec_attr, 0, sizeof sec_attr ); memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr; sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE; sec_attr.bInheritHandle = FALSE;
/* Build the command line. */ /* Build the command line. */
err = build_w32_commandline (pgmname, argv, &cmdline); err = build_w32_commandline (pgmname, argv, &cmdline);
if (err) if (err)
return err; return err;
/* Create a pipe. */ /* Create a pipe. */
if (create_inheritable_pipe (rp)) if (create_inheritable_pipe (rp))
@ -529,7 +539,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
xfree (cmdline); xfree (cmdline);
return err; return err;
} }
/* Start the process. Note that we can't run the PREEXEC function /* Start the process. Note that we can't run the PREEXEC function
because this would change our own environment. */ because this would change our own environment. */
memset (&si, 0, sizeof si); memset (&si, 0, sizeof si);
@ -543,7 +553,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
cr_flags = (CREATE_DEFAULT_ERROR_MODE cr_flags = (CREATE_DEFAULT_ERROR_MODE
| ((flags & 128)? DETACHED_PROCESS : 0) | ((flags & 128)? DETACHED_PROCESS : 0)
| GetPriorityClass (GetCurrentProcess ()) | GetPriorityClass (GetCurrentProcess ())
| CREATE_SUSPENDED); | CREATE_SUSPENDED);
/* log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */ /* log_debug ("CreateProcess, path=`%s' cmdline=`%s'\n", pgmname, cmdline); */
if (!CreateProcess (pgmname, /* Program to start. */ if (!CreateProcess (pgmname, /* Program to start. */
cmdline, /* Command line arguments. */ cmdline, /* Command line arguments. */
@ -568,12 +578,12 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
/* Close the other end of the pipe. */ /* Close the other end of the pipe. */
CloseHandle (fd_to_handle (rp[1])); CloseHandle (fd_to_handle (rp[1]));
/* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */ /* log_debug ("CreateProcess ready: hProcess=%p hThread=%p" */
/* " dwProcessID=%d dwThreadId=%d\n", */ /* " dwProcessID=%d dwThreadId=%d\n", */
/* pi.hProcess, pi.hThread, */ /* pi.hProcess, pi.hThread, */
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
/* Fixme: For unknown reasons AllowSetForegroundWindow returns an /* Fixme: For unknown reasons AllowSetForegroundWindow returns an
invalid argument error if we pass the correct processID to invalid argument error if we pass the correct processID to
it. As a workaround we use -1 (ASFW_ANY). */ it. As a workaround we use -1 (ASFW_ANY). */
@ -582,7 +592,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
/* Process has been created suspended; resume it now. */ /* Process has been created suspended; resume it now. */
ResumeThread (pi.hThread); ResumeThread (pi.hThread);
CloseHandle (pi.hThread); CloseHandle (pi.hThread);
{ {
int x; int x;
@ -590,7 +600,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
x = _open_osfhandle (rp[0], 0); x = _open_osfhandle (rp[0], 0);
if (x == -1) if (x == -1)
log_error ("failed to translate osfhandle %p\n", (void*)rp[0] ); log_error ("failed to translate osfhandle %p\n", (void*)rp[0] );
else else
*statusfile = fdopen (x, "r"); *statusfile = fdopen (x, "r");
} }
if (!*statusfile) if (!*statusfile)
@ -626,7 +636,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
return err; return err;
} }
#ifdef USE_GNU_PTH #ifdef USE_GNU_PTH
*pid = pth_fork? pth_fork () : fork (); *pid = pth_fork? pth_fork () : fork ();
#else #else
*pid = fork (); *pid = fork ();
@ -641,7 +651,7 @@ gnupg_spawn_process (const char *pgmname, const char *argv[],
} }
if (!*pid) if (!*pid)
{ {
gcry_control (GCRYCTL_TERM_SECMEM); gcry_control (GCRYCTL_TERM_SECMEM);
/* Run child. */ /* Run child. */
do_exec (pgmname, argv, fd, fdout, rp[1], preexec); do_exec (pgmname, argv, fd, fdout, rp[1], preexec);
@ -695,11 +705,11 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
memset (&sec_attr, 0, sizeof sec_attr ); memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr; sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE; sec_attr.bInheritHandle = FALSE;
/* Build the command line. */ /* Build the command line. */
err = build_w32_commandline (pgmname, argv, &cmdline); err = build_w32_commandline (pgmname, argv, &cmdline);
if (err) if (err)
return err; return err;
memset (&si, 0, sizeof si); memset (&si, 0, sizeof si);
si.cb = sizeof (si); si.cb = sizeof (si);
@ -746,7 +756,7 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
/* Process has been created suspended; resume it now. */ /* Process has been created suspended; resume it now. */
ResumeThread (pi.hThread); ResumeThread (pi.hThread);
CloseHandle (pi.hThread); CloseHandle (pi.hThread);
*pid = handle_to_pid (pi.hProcess); *pid = handle_to_pid (pi.hProcess);
return 0; return 0;
@ -754,7 +764,7 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
#else /* !HAVE_W32_SYSTEM */ #else /* !HAVE_W32_SYSTEM */
gpg_error_t err; gpg_error_t err;
#ifdef USE_GNU_PTH #ifdef USE_GNU_PTH
*pid = pth_fork? pth_fork () : fork (); *pid = pth_fork? pth_fork () : fork ();
#else #else
*pid = fork (); *pid = fork ();
@ -767,7 +777,7 @@ gnupg_spawn_process_fd (const char *pgmname, const char *argv[],
} }
if (!*pid) if (!*pid)
{ {
gcry_control (GCRYCTL_TERM_SECMEM); gcry_control (GCRYCTL_TERM_SECMEM);
/* Run child. */ /* Run child. */
do_exec (pgmname, argv, infd, outfd, errfd, NULL); do_exec (pgmname, argv, infd, outfd, errfd, NULL);
@ -805,7 +815,7 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
been implemented. A special W32 pth system call would even be been implemented. A special W32 pth system call would even be
better. */ better. */
code = WaitForSingleObject (proc, INFINITE); code = WaitForSingleObject (proc, INFINITE);
switch (code) switch (code)
{ {
case WAIT_FAILED: case WAIT_FAILED:
log_error (_("waiting for process %d to terminate failed: %s\n"), log_error (_("waiting for process %d to terminate failed: %s\n"),
@ -872,7 +882,7 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
} }
else if (WIFEXITED (status) && WEXITSTATUS (status)) else if (WIFEXITED (status) && WEXITSTATUS (status))
{ {
if (!exitcode) if (!exitcode)
log_error (_("error running `%s': exit status %d\n"), pgmname, log_error (_("error running `%s': exit status %d\n"), pgmname,
WEXITSTATUS (status)); WEXITSTATUS (status));
@ -885,7 +895,7 @@ gnupg_wait_process (const char *pgmname, pid_t pid, int *exitcode)
log_error (_("error running `%s': terminated\n"), pgmname); log_error (_("error running `%s': terminated\n"), pgmname);
ec = GPG_ERR_GENERAL; ec = GPG_ERR_GENERAL;
} }
else else
{ {
if (exitcode) if (exitcode)
*exitcode = 0; *exitcode = 0;
@ -911,7 +921,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
#ifdef HAVE_W32_SYSTEM #ifdef HAVE_W32_SYSTEM
gpg_error_t err; gpg_error_t err;
SECURITY_ATTRIBUTES sec_attr; SECURITY_ATTRIBUTES sec_attr;
PROCESS_INFORMATION pi = PROCESS_INFORMATION pi =
{ {
NULL, /* Returns process handle. */ NULL, /* Returns process handle. */
0, /* Returns primary thread handle. */ 0, /* Returns primary thread handle. */
@ -936,11 +946,11 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
memset (&sec_attr, 0, sizeof sec_attr ); memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr; sec_attr.nLength = sizeof sec_attr;
sec_attr.bInheritHandle = FALSE; sec_attr.bInheritHandle = FALSE;
/* Build the command line. */ /* Build the command line. */
err = build_w32_commandline (pgmname, argv, &cmdline); err = build_w32_commandline (pgmname, argv, &cmdline);
if (err) if (err)
return err; return err;
/* Start the process. */ /* Start the process. */
memset (&si, 0, sizeof si); memset (&si, 0, sizeof si);
@ -951,7 +961,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
cr_flags = (CREATE_DEFAULT_ERROR_MODE cr_flags = (CREATE_DEFAULT_ERROR_MODE
| GetPriorityClass (GetCurrentProcess ()) | GetPriorityClass (GetCurrentProcess ())
| CREATE_NEW_PROCESS_GROUP | CREATE_NEW_PROCESS_GROUP
| DETACHED_PROCESS); | DETACHED_PROCESS);
/* log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */ /* log_debug ("CreateProcess(detached), path=`%s' cmdline=`%s'\n", */
/* pgmname, cmdline); */ /* pgmname, cmdline); */
if (!CreateProcess (pgmname, /* Program to start. */ if (!CreateProcess (pgmname, /* Program to start. */
@ -978,7 +988,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
/* pi.hProcess, pi.hThread, */ /* pi.hProcess, pi.hThread, */
/* (int) pi.dwProcessId, (int) pi.dwThreadId); */ /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
CloseHandle (pi.hThread); CloseHandle (pi.hThread);
return 0; return 0;
@ -992,7 +1002,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
if (access (pgmname, X_OK)) if (access (pgmname, X_OK))
return gpg_error_from_syserror (); return gpg_error_from_syserror ();
#ifdef USE_GNU_PTH #ifdef USE_GNU_PTH
pid = pth_fork? pth_fork () : fork (); pid = pth_fork? pth_fork () : fork ();
#else #else
pid = fork (); pid = fork ();
@ -1004,7 +1014,7 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
} }
if (!pid) if (!pid)
{ {
pid_t pid2; pid_t pid2;
gcry_control (GCRYCTL_TERM_SECMEM); gcry_control (GCRYCTL_TERM_SECMEM);
if (setsid() == -1 || chdir ("/")) if (setsid() == -1 || chdir ("/"))
@ -1018,12 +1028,12 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[],
if (envp) if (envp)
for (i=0; envp[i]; i++) for (i=0; envp[i]; i++)
putenv (xstrdup (envp[i])); putenv (xstrdup (envp[i]));
do_exec (pgmname, argv, -1, -1, -1, NULL); do_exec (pgmname, argv, -1, -1, -1, NULL);
/*NOTREACHED*/ /*NOTREACHED*/
} }
if (waitpid (pid, NULL, 0) == -1) if (waitpid (pid, NULL, 0) == -1)
log_error ("waitpid failed in gnupg_spawn_process_detached: %s", log_error ("waitpid failed in gnupg_spawn_process_detached: %s",
strerror (errno)); strerror (errno));