summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2022-10-31 11:07:57 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2022-10-31 11:07:57 +0900
commit6c20e8393eba4a9f330143b2158e28ea594cbadd (patch)
treee36258183639ef2df818806168e3ea34351ec89e
parent43c1e85fe29a52a9debc068d97c5860a4694b821 (diff)
downloadlibgpg-error-6c20e8393eba4a9f330143b2158e28ea594cbadd.tar.gz
spawn: Fix spawn_cb of gpgrt_spawn_process_fd.
* src/gpg-error.def.in (gpgrt_close_all_fds): New. * src/gpg-error.vers (gpgrt_close_all_fds): New. * src/gpg-error.h.in (GPGRT_SPAWN_INHERIT_FILE): New. (gpgrt_spawn_process_fd): SPAWN_CB having return value. * src/gpgrt-int.h (_gpgrt_spawn_process_fd): SPAWN_CB change. * src/spawn-posix.c (_gpgrt_close_all_fds): Rename from close_all_fds, and export it. (do_exec): Support the case not closing fds. (_gpgrt_spawn_process_fd): Handle return value of SPAWN_CB to determine closing all fds or not. * src/spawn-w32.c (_gpgrt_spawn_process_fd): Run SPAWN_CB. (_gpgrt_close_all_fds): New. * src/visibility.c (gpgrt_close_all_fds): New. * src/visibility.h (gpgrt_close_all_fds): New. -- Now, we have the API of gpgrt_spawn_process_fd for POSIX and Windows. Giving portable semantics for spawning a process is difficult, and it is still difficult for users to writing a function for SPAWN_CB with portability, but gpgrt_spawn_process_fd gives the feature of spawning a process. GnuPG-bug-id: 6249 Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--src/gpg-error.def.in2
-rw-r--r--src/gpg-error.h.in12
-rw-r--r--src/gpg-error.vers1
-rw-r--r--src/gpgrt-int.h17
-rw-r--r--src/spawn-posix.c19
-rw-r--r--src/spawn-w32.c22
-rw-r--r--src/visibility.c12
-rw-r--r--src/visibility.h2
8 files changed, 63 insertions, 24 deletions
diff --git a/src/gpg-error.def.in b/src/gpg-error.def.in
index ac8f2f6..f94c6f4 100644
--- a/src/gpg-error.def.in
+++ b/src/gpg-error.def.in
@@ -242,4 +242,6 @@ EXPORTS
gpgrt_utf8_to_wchar @186
gpgrt_wchar_to_utf8 @187
+ gpgrt_close_all_fds @188
+
;; end of file with public symbols for Windows.
diff --git a/src/gpg-error.h.in b/src/gpg-error.h.in
index b7cfdcf..ce5c76a 100644
--- a/src/gpg-error.h.in
+++ b/src/gpg-error.h.in
@@ -1084,6 +1084,9 @@ void _gpgrt_log_assert (const char *expr, const char *file, int line,
/*
* Spawn functions
*/
+/* Internal flag to ihnerit file descriptor/handle */
+#define GPGRT_SPAWN_INHERIT_FILE 1
+
#define GPGRT_SPAWN_NONBLOCK 16 /* Set the streams to non-blocking. */
#define GPGRT_SPAWN_RUN_ASFW 64 /* Use AllowSetForegroundWindow on W32. */
#define GPGRT_SPAWN_DETACHED 128 /* Start the process in the background. */
@@ -1110,14 +1113,14 @@ gpg_err_code_t gpgrt_spawn_process (const char *pgmname, const char *argv[],
/* Fork and exec PGNNAME and connect the process to the given FDs. */
gpg_err_code_t gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
int infd, int outfd, int errfd,
- void (*after_fork_cb)(void *),
- void *after_fork_cb_arg,
+ int (*spawn_cb) (void *),
+ void *spawn_cb_arg,
pid_t *pid);
/* Fork and exec PGMNAME as a detached process. */
gpg_err_code_t gpgrt_spawn_process_detached (const char *pgmname,
const char *argv[],
- const char *envp[] );
+ const char *envp[]);
/* Wait for a single process. */
gpg_err_code_t gpgrt_wait_process (const char *pgmname, pid_t pid, int hang,
@@ -1132,6 +1135,9 @@ void gpgrt_kill_process (pid_t pid);
/* Release process resources identified by PID. */
void gpgrt_release_process (pid_t pid);
+
+/* Close all file resources (descriptors), except KEEP_FDS. */
+void gpgrt_close_all_fds (int from, int *keep_fds);
/*
* Option parsing.
diff --git a/src/gpg-error.vers b/src/gpg-error.vers
index 4182da0..8884e47 100644
--- a/src/gpg-error.vers
+++ b/src/gpg-error.vers
@@ -179,6 +179,7 @@ GPG_ERROR_1.0 {
gpgrt_wait_processes;
gpgrt_kill_process;
gpgrt_release_process;
+ gpgrt_close_all_fds;
gpgrt_argparse;
gpgrt_argparser;
diff --git a/src/gpgrt-int.h b/src/gpgrt-int.h
index b95b44c..c414272 100644
--- a/src/gpgrt-int.h
+++ b/src/gpgrt-int.h
@@ -696,15 +696,19 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
* The arguments for the process are expected in the NULL terminated
* array ARGV. The program name itself should not be included there.
* Calling gpgrt_wait_process and gpgrt_release_process is required.
- * Returns 0 on success or an error code. If AFTER_FORK_CB is not
- * NULL, the given function will be called right after the fork, by
- * child process.
+ * Returns 0 on success or an error code. If SPAWN_CB is not NULL,
+ * the given function will be called with SPAWN_CB_ARG to determine if
+ * file descriptors/handles should be inherited or not. The callback
+ * function should return 1 to ask keeping file descriptors/handles.
+ * If SPAWN_CB is NULL, or it returns 0, all file descriptors (except
+ * INFD, OUTFD, and ERRFD) will be closed on POSIX machine. On POSIX
+ * machine, it is called right after the fork, by child process.
*/
gpg_err_code_t _gpgrt_spawn_process_fd (const char *pgmname,
const char *argv[],
int infd, int outfd, int errfd,
- void (*after_fork_cb)(void *),
- void *after_fork_cb_arg,
+ int (*spawn_cb) (void *),
+ void *spawn_cb_arg,
pid_t *pid);
/* Spawn a new process and immediately detach from it. The name of
@@ -758,6 +762,9 @@ void _gpgrt_kill_process (pid_t pid);
* It is a nop if PID is invalid. */
void _gpgrt_release_process (pid_t pid);
+/* Close all file resources (descriptors), except KEEP_FDS. */
+void _gpgrt_close_all_fds (int from, int *keep_fds);
+
/*
* Local prototypes for argparse.
diff --git a/src/spawn-posix.c b/src/spawn-posix.c
index 3ac79ff..6914b0b 100644
--- a/src/spawn-posix.c
+++ b/src/spawn-posix.c
@@ -163,8 +163,8 @@ get_max_fds (void)
* EXCEPT is not NULL, it is expected to be a list of file descriptors
* which shall not be closed. This list shall be sorted in ascending
* order with the end marked by -1. */
-static void
-close_all_fds (int first, int *except)
+void
+_gpgrt_close_all_fds (int first, int *except)
{
int max_fd = get_max_fds ();
int fd, i, except_start;
@@ -319,7 +319,8 @@ do_exec (const char *pgmname, const char *argv[],
}
/* Close all other files. */
- close_all_fds (3, except);
+ if (!(flags & GPGRT_SPAWN_INHERIT_FILE))
+ _gpgrt_close_all_fds (3, except);
execv (pgmname, arg_list);
/* No way to print anything, as we have may have closed all streams. */
@@ -535,11 +536,12 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
gpg_err_code_t
_gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
int infd, int outfd, int errfd,
- void (*after_fork_cb)(void *),
- void *after_fork_cb_arg,
+ int (*spawn_cb) (void *),
+ void *spawn_cb_arg,
pid_t *pid)
{
gpg_error_t err;
+ int ask_inherit_fds = 0;
_gpgrt_pre_syscall ();
*pid = fork ();
@@ -553,11 +555,12 @@ _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
if (!*pid)
{
- if (after_fork_cb)
- (*after_fork_cb) (after_fork_cb_arg);
+ if (spawn_cb)
+ ask_inherit_fds = (*spawn_cb) (spawn_cb_arg);
/* Run child. */
- do_exec (pgmname, argv, infd, outfd, errfd, NULL, 0);
+ do_exec (pgmname, argv, infd, outfd, errfd, NULL,
+ ask_inherit_fds? GPGRT_SPAWN_INHERIT_FILE : 0);
/*NOTREACHED*/
}
diff --git a/src/spawn-w32.c b/src/spawn-w32.c
index 963b6a5..d17f971 100644
--- a/src/spawn-w32.c
+++ b/src/spawn-w32.c
@@ -642,8 +642,8 @@ _gpgrt_spawn_process (const char *pgmname, const char *argv[],
gpg_err_code_t
_gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
int infd, int outfd, int errfd,
- void (*after_fork_cb)(void *),
- void *after_fork_cb_arg,
+ int (*spawn_cb) (void *),
+ void *spawn_cb_arg,
pid_t *pid)
{
gpg_err_code_t err;
@@ -653,9 +653,10 @@ _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
char *cmdline;
int ret, i;
HANDLE stdhd[3];
+ int ask_inherit = 0;
- (void)after_fork_cb;
- (void)after_fork_cb_arg;
+ if (spawn_cb)
+ ask_inherit = (*spawn_cb) (spawn_cb_arg);
/* Setup return values. */
*pid = (pid_t)INVALID_HANDLE_VALUE;
@@ -663,7 +664,11 @@ _gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
/* Prepare security attributes. */
memset (&sec_attr, 0, sizeof sec_attr );
sec_attr.nLength = sizeof sec_attr;
- sec_attr.bInheritHandle = FALSE;
+
+ if (ask_inherit)
+ sec_attr.bInheritHandle = TRUE;
+ else
+ sec_attr.bInheritHandle = FALSE;
/* Build the command line. */
err = build_w32_commandline (pgmname, argv, &cmdline);
@@ -926,3 +931,10 @@ _gpgrt_release_process (pid_t pid)
CloseHandle (process);
}
}
+
+void
+_gpgrt_close_all_fds (int from, int *keep_fds)
+{
+ (void)from;
+ (void)keep_fds;
+}
diff --git a/src/visibility.c b/src/visibility.c
index dba48b8..577a2be 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1112,12 +1112,12 @@ gpgrt_spawn_process (const char *pgmname, const char *argv[],
gpg_err_code_t
gpgrt_spawn_process_fd (const char *pgmname, const char *argv[],
int infd, int outfd, int errfd,
- void (*after_fork_cb)(void *),
- void *after_fork_cb_arg,
+ int (*spawn_cb)(void *),
+ void *spawn_cb_arg,
pid_t *pid)
{
return _gpgrt_spawn_process_fd (pgmname, argv, infd, outfd, errfd,
- after_fork_cb, after_fork_cb_arg, pid);
+ spawn_cb, spawn_cb_arg, pid);
}
gpg_err_code_t
@@ -1152,6 +1152,12 @@ gpgrt_release_process (pid_t pid)
_gpgrt_release_process (pid);
}
+void
+gpgrt_close_all_fds (int from, int *keep_fds)
+{
+ _gpgrt_close_all_fds (from, keep_fds);
+}
+
int
gpgrt_argparse (estream_t fp, gpgrt_argparse_t *arg, gpgrt_opt_t *opts)
diff --git a/src/visibility.h b/src/visibility.h
index 2819394..a3ed6fc 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -207,6 +207,7 @@ MARK_VISIBLE (gpgrt_wait_process)
MARK_VISIBLE (gpgrt_wait_processes)
MARK_VISIBLE (gpgrt_kill_process)
MARK_VISIBLE (gpgrt_release_process)
+MARK_VISIBLE (gpgrt_close_all_fds)
MARK_VISIBLE (gpgrt_argparse)
MARK_VISIBLE (gpgrt_argparser)
@@ -394,6 +395,7 @@ MARK_VISIBLE (gpgrt_absfnameconcat)
#define gpgrt_wait_processes _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_kill_process _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_release_process _gpgrt_USE_UNDERSCORED_FUNCTION
+#define gpgrt_close_all_fds _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_argparse _gpgrt_USE_UNDERSCORED_FUNCTION
#define gpgrt_argparser _gpgrt_USE_UNDERSCORED_FUNCTION