mirror of
git://sourceware.org/git/glibc.git
synced 2024-12-21 04:31:04 +08:00
177 lines
4.6 KiB
C
177 lines
4.6 KiB
C
/* Test posix_spawn setsid attribute.
|
|
Copyright (C) 2017-2024 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
The GNU C Library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<https://www.gnu.org/licenses/>. */
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <getopt.h>
|
|
#include <intprops.h>
|
|
#include <paths.h>
|
|
#include <spawn.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/resource.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include <support/check.h>
|
|
#include <support/xunistd.h>
|
|
#include <support/temp_file.h>
|
|
#include <tst-spawn.h>
|
|
|
|
/* Nonzero if the program gets called via `exec'. */
|
|
static int restart;
|
|
|
|
/* Hold the four initial argument used to respawn the process, plus
|
|
the extra '--direct' and '--restart', and a final NULL. */
|
|
static char *initial_argv[7];
|
|
static int initial_argv_count;
|
|
|
|
#define CMDLINE_OPTIONS \
|
|
{ "restart", no_argument, &restart, 1 },
|
|
|
|
static char *pidfile;
|
|
|
|
static pid_t
|
|
read_child_sid (void)
|
|
{
|
|
int pidfd = xopen (pidfile, O_RDONLY, 0);
|
|
|
|
char buf[INT_STRLEN_BOUND (pid_t)];
|
|
ssize_t n = read (pidfd, buf, sizeof (buf));
|
|
TEST_VERIFY (n < sizeof buf && n >= 0);
|
|
buf[n] = '\0';
|
|
|
|
/* We only expect to read the PID. */
|
|
char *endp;
|
|
long int rpid = strtol (buf, &endp, 10);
|
|
TEST_VERIFY (endp != buf);
|
|
|
|
xclose (pidfd);
|
|
|
|
return rpid;
|
|
}
|
|
|
|
/* Called on process re-execution, write down the session id on PIDFILE. */
|
|
static void
|
|
handle_restart (const char *pidfile)
|
|
{
|
|
int pidfd = xopen (pidfile, O_WRONLY, 0);
|
|
|
|
char buf[INT_STRLEN_BOUND (pid_t)];
|
|
int s = snprintf (buf, sizeof buf, "%d", getsid (0));
|
|
size_t n = write (pidfd, buf, s);
|
|
TEST_VERIFY (n == s);
|
|
|
|
xclose (pidfd);
|
|
}
|
|
|
|
static void
|
|
do_test_setsid (bool test_setsid)
|
|
{
|
|
/* Current session ID. */
|
|
pid_t sid = getsid (0);
|
|
TEST_VERIFY (sid != (pid_t) -1);
|
|
|
|
posix_spawnattr_t attrp;
|
|
TEST_COMPARE (posix_spawnattr_init (&attrp), 0);
|
|
if (test_setsid)
|
|
TEST_COMPARE (posix_spawnattr_setflags (&attrp, POSIX_SPAWN_SETSID), 0);
|
|
|
|
/* 1 or 4 elements from initial_argv:
|
|
+ path to ld.so optional
|
|
+ --library-path optional
|
|
+ the library path optional
|
|
+ application name
|
|
+ --direct
|
|
+ --restart
|
|
+ pidfile */
|
|
int argv_size = initial_argv_count + 2;
|
|
char *args[argv_size];
|
|
int argc = 0;
|
|
|
|
for (char **arg = initial_argv; *arg != NULL; arg++)
|
|
args[argc++] = *arg;
|
|
args[argc++] = pidfile;
|
|
args[argc] = NULL;
|
|
TEST_VERIFY (argc < argv_size);
|
|
|
|
PID_T_TYPE pid;
|
|
TEST_COMPARE (POSIX_SPAWN (&pid, args[0], NULL, &attrp, args, environ), 0);
|
|
TEST_COMPARE (posix_spawnattr_destroy (&attrp), 0);
|
|
|
|
siginfo_t sinfo;
|
|
TEST_COMPARE (WAITID (P_PID, pid, &sinfo, WEXITED), 0);
|
|
TEST_COMPARE (sinfo.si_code, CLD_EXITED);
|
|
TEST_COMPARE (sinfo.si_status, 0);
|
|
|
|
pid_t child_sid = read_child_sid ();
|
|
|
|
/* Child should have a different session ID than parent. */
|
|
TEST_VERIFY (child_sid != (pid_t) -1);
|
|
|
|
if (test_setsid)
|
|
TEST_VERIFY (child_sid != sid);
|
|
else
|
|
TEST_VERIFY (child_sid == sid);
|
|
}
|
|
|
|
static int
|
|
do_test (int argc, char *argv[])
|
|
{
|
|
/* We must have either:
|
|
|
|
- one or four parameters if called initially:
|
|
+ argv[1]: path for ld.so optional
|
|
+ argv[2]: "--library-path" optional
|
|
+ argv[3]: the library path optional
|
|
+ argv[4]: the application name
|
|
|
|
- six parameters left if called through re-execution:
|
|
+ argv[5/1]: the application name
|
|
+ argv[6/2]: the pidfile
|
|
|
|
* When built with --enable-hardcoded-path-in-tests or issued without
|
|
using the loader directly. */
|
|
|
|
if (restart)
|
|
{
|
|
handle_restart (argv[1]);
|
|
return 0;
|
|
}
|
|
|
|
TEST_VERIFY_EXIT (argc == 2 || argc == 5);
|
|
|
|
int i;
|
|
for (i = 0; i < argc - 1; i++)
|
|
initial_argv[i] = argv[i + 1];
|
|
initial_argv[i++] = (char *) "--direct";
|
|
initial_argv[i++] = (char *) "--restart";
|
|
initial_argv_count = i;
|
|
|
|
create_temp_file ("tst-posix_spawn-setsid-", &pidfile);
|
|
|
|
do_test_setsid (false);
|
|
do_test_setsid (true);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define TEST_FUNCTION_ARGV do_test
|
|
#include <support/test-driver.c>
|