/* 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
. */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/* 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