* Copyright (c) 2024 FUJITSU LIMITED. All Rights Reserved.
* Author: Ma Xinjian <maxj.fnst@fujitsu.com>
*/
* Verify that, rt_sigqueueinfo(2) sets errno to
*
* - EINVAL if sig is invalid
* - EPERM if uinfo->si_code is invalid
* - ESRCH if no thread group matching tgid is found
*/
#include <pwd.h>
#include <signal.h>
#include "config.h"
#include "tst_test.h"
#ifdef HAVE_STRUCT_SIGACTION_SA_SIGACTION
#include "rt_sigqueueinfo.h"
static siginfo_t siginfo_einval;
static siginfo_t siginfo_eperm;
static siginfo_t siginfo_esrch;
static pid_t tgid_notfound = -1;
static struct test_case_t {
pid_t *tgid;
int sig;
siginfo_t *uinfo;
int expected_errno;
char *desc;
} tcases[] = {
{NULL, -1, &siginfo_einval, EINVAL, "sig is invalid"},
{NULL, SIGUSR1, &siginfo_eperm, EPERM, "uinfo->si_code is invalid"},
{&tgid_notfound, SIGUSR1, &siginfo_esrch, ESRCH,
"no thread group matching tgid is found"},
};
static void setup(void)
{
siginfo_einval.si_code = SI_QUEUE;
siginfo_eperm.si_code = 0;
siginfo_esrch.si_code = SI_QUEUE;
}
static void parent_do(struct test_case_t *tc, pid_t pid)
{
pid_t real_pid;
if (tc->tgid)
real_pid = *(tc->tgid);
else
real_pid = pid;
TST_EXP_FAIL(sys_rt_sigqueueinfo(real_pid, tc->sig, tc->uinfo),
tc->expected_errno, "%s", tc->desc);
TST_CHECKPOINT_WAKE(0);
}
static void child_do(void)
{
TST_CHECKPOINT_WAIT(0);
}
static void verify_rt_sigqueueinfo(unsigned int i)
{
struct test_case_t *tc = &tcases[i];
pid_t pid = SAFE_FORK();
if (!pid) {
child_do();
exit(0);
}
parent_do(tc, pid);
SAFE_WAITPID(pid, NULL, 0);
}
static struct tst_test test = {
.setup = setup,
.tcnt = ARRAY_SIZE(tcases),
.test = verify_rt_sigqueueinfo,
.forks_child = 1,
.needs_checkpoints = 1,
.bufs = (struct tst_buffers []) {
{&siginfo_einval, .size = sizeof(siginfo_einval)},
{&siginfo_eperm, .size = sizeof(siginfo_eperm)},
{&siginfo_esrch, .size = sizeof(siginfo_esrch)},
{},
}
};
#else
TST_TEST_TCONF("This system does not support rt_sigqueueinfo()");
#endif