mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-27 07:56:14 +01:00
gspawn: Audit for async-signal-safety
Functions called between `fork()` and `exec()` have to be async-signal-safe. Add a comment to each function which is called in that context, and `FIXME` comments to the non-async-signal-safe functions which end up being called as leaves of the call graph. The following commits will fix those `FIXME`s. See `man 7 signal-safety`. Signed-off-by: Philip Withnall <withnall@endlessm.com> Helps: #2140
This commit is contained in:
parent
50ce2792ff
commit
0e05ef7750
@ -262,6 +262,9 @@ g_spawn_async (const gchar *working_directory,
|
||||
/* Avoids a danger in threaded situations (calling close()
|
||||
* on a file descriptor twice, and another thread has
|
||||
* re-opened it since the first close)
|
||||
*
|
||||
* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)).
|
||||
*/
|
||||
static void
|
||||
close_and_invalidate (gint *fd)
|
||||
@ -270,6 +273,7 @@ close_and_invalidate (gint *fd)
|
||||
return;
|
||||
else
|
||||
{
|
||||
/* FIXME: g_close() is not async-signal-safe on failure. */
|
||||
(void) g_close (*fd, NULL);
|
||||
*fd = -1;
|
||||
}
|
||||
@ -1081,6 +1085,8 @@ g_spawn_check_exit_status (gint exit_status,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static gssize
|
||||
write_all (gint fd, gconstpointer vbuf, gsize to_write)
|
||||
{
|
||||
@ -1104,6 +1110,8 @@ write_all (gint fd, gconstpointer vbuf, gsize to_write)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
G_GNUC_NORETURN
|
||||
static void
|
||||
write_err_and_exit (gint fd, gint msg)
|
||||
@ -1116,6 +1124,8 @@ write_err_and_exit (gint fd, gint msg)
|
||||
_exit (1);
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static int
|
||||
set_cloexec (void *data, gint fd)
|
||||
{
|
||||
@ -1125,6 +1135,8 @@ set_cloexec (void *data, gint fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static gint
|
||||
safe_close (gint fd)
|
||||
{
|
||||
@ -1137,6 +1149,8 @@ safe_close (gint fd)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
G_GNUC_UNUSED static int
|
||||
close_func (void *data, int fd)
|
||||
{
|
||||
@ -1156,6 +1170,8 @@ struct linux_dirent64
|
||||
char d_name[]; /* Filename (null-terminated) */
|
||||
};
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static gint
|
||||
filename_to_fd (const char *p)
|
||||
{
|
||||
@ -1169,6 +1185,7 @@ filename_to_fd (const char *p)
|
||||
|
||||
while ((c = *p++) != '\0')
|
||||
{
|
||||
/* FIXME: g_ascii_isdigit() is not necessarily async-signal-safe. */
|
||||
if (!g_ascii_isdigit (c))
|
||||
return -1;
|
||||
c -= '0';
|
||||
@ -1184,6 +1201,8 @@ filename_to_fd (const char *p)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static int
|
||||
safe_fdwalk (int (*cb)(void *data, int fd), void *data)
|
||||
{
|
||||
@ -1237,7 +1256,9 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data)
|
||||
}
|
||||
|
||||
/* If /proc is not mounted or not accessible we fall back to the old
|
||||
* rlimit trick */
|
||||
* rlimit trick.
|
||||
*
|
||||
* FIXME: getrlimit() and sysconf() are not async-signal-safe. */
|
||||
|
||||
#endif
|
||||
|
||||
@ -1257,6 +1278,8 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static void
|
||||
safe_closefrom (int lowfd)
|
||||
{
|
||||
@ -1289,6 +1312,8 @@ safe_closefrom (int lowfd)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static gint
|
||||
safe_dup2 (gint fd1, gint fd2)
|
||||
{
|
||||
@ -1301,6 +1326,8 @@ safe_dup2 (gint fd1, gint fd2)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static gint
|
||||
safe_open (const char *path, gint mode)
|
||||
{
|
||||
@ -1321,6 +1348,8 @@ enum
|
||||
CHILD_FORK_FAILED
|
||||
};
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)) until it calls exec(). */
|
||||
static void
|
||||
do_exec (gint child_err_report_fd,
|
||||
gint stdin_fd,
|
||||
@ -1358,6 +1387,7 @@ do_exec (gint child_err_report_fd,
|
||||
else if (!child_inherits_stdin)
|
||||
{
|
||||
/* Keep process from blocking on a read of stdin */
|
||||
/* FIXME: g_assert() is not async-signal-safe on failure. */
|
||||
gint read_null = safe_open ("/dev/null", O_RDONLY);
|
||||
g_assert (read_null != -1);
|
||||
safe_dup2 (read_null, 0);
|
||||
@ -1376,6 +1406,7 @@ do_exec (gint child_err_report_fd,
|
||||
}
|
||||
else if (stdout_to_null)
|
||||
{
|
||||
/* FIXME: g_assert() is not async-signal-safe on failure. */
|
||||
gint write_null = safe_open ("/dev/null", O_WRONLY);
|
||||
g_assert (write_null != -1);
|
||||
safe_dup2 (write_null, 1);
|
||||
@ -2113,6 +2144,8 @@ cleanup_and_fail:
|
||||
|
||||
/* Based on execvp from GNU C Library */
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)) until it calls exec(). */
|
||||
static void
|
||||
script_execute (const gchar *file,
|
||||
gchar **argv,
|
||||
@ -2127,6 +2160,7 @@ script_execute (const gchar *file,
|
||||
{
|
||||
gchar **new_argv;
|
||||
|
||||
/* FIXME: This is not async-signal-safe */
|
||||
new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */
|
||||
|
||||
new_argv[0] = (char *) "/bin/sh";
|
||||
@ -2147,6 +2181,8 @@ script_execute (const gchar *file,
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)). */
|
||||
static gchar*
|
||||
my_strchrnul (const gchar *str, gchar c)
|
||||
{
|
||||
@ -2157,6 +2193,8 @@ my_strchrnul (const gchar *str, gchar c)
|
||||
return p;
|
||||
}
|
||||
|
||||
/* This function is called between fork() and exec() and hence must be
|
||||
* async-signal-safe (see signal-safety(7)) until it calls exec(). */
|
||||
static gint
|
||||
g_execute (const gchar *file,
|
||||
gchar **argv,
|
||||
@ -2190,6 +2228,7 @@ g_execute (const gchar *file,
|
||||
gsize len;
|
||||
gsize pathlen;
|
||||
|
||||
/* FIXME: getenv() is not async-signal-safe */
|
||||
path = NULL;
|
||||
if (search_path_from_envp)
|
||||
path = g_environ_getenv (envp, "PATH");
|
||||
@ -2213,6 +2252,7 @@ g_execute (const gchar *file,
|
||||
|
||||
len = strlen (file) + 1;
|
||||
pathlen = strlen (path);
|
||||
/* FIXME: malloc() is not async-signal-safe */
|
||||
freeme = name = g_malloc (pathlen + len + 1);
|
||||
|
||||
/* Copy the file name at the top, including '\0' */
|
||||
|
Loading…
Reference in New Issue
Block a user