19649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin/*
29649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * This file is part of rt_sigsuspend strace test.
39649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin *
49649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
59649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * All rights reserved.
69649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin *
79649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * Redistribution and use in source and binary forms, with or without
89649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * modification, are permitted provided that the following conditions
99649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * are met:
109649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * 1. Redistributions of source code must retain the above copyright
119649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin *    notice, this list of conditions and the following disclaimer.
129649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * 2. Redistributions in binary form must reproduce the above copyright
139649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin *    notice, this list of conditions and the following disclaimer in the
149649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin *    documentation and/or other materials provided with the distribution.
159649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * 3. The name of the author may not be used to endorse or promote products
169649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin *    derived from this software without specific prior written permission.
179649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin *
189649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
199649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
209649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
219649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
229649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
239649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
249649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
259649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
269649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
279649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
289649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin */
299649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
309649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin#include "tests.h"
316a2f43ce6469c06d0244a07cea3d04f3740a66ceDmitry V. Levin#include <asm/unistd.h>
329649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
339649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin#ifdef __NR_rt_sigsuspend
349649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
359649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin# include <assert.h>
369649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin# include <errno.h>
379649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin# include <signal.h>
389649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin# include <stdio.h>
399649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin# include <stdint.h>
409649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin# include <string.h>
419649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin# include <unistd.h>
429649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
439649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levinstatic long
449649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levink_sigsuspend(const sigset_t *const set, const unsigned long size)
459649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin{
469649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	return syscall(__NR_rt_sigsuspend, set, size);
479649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin}
489649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
499649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levinstatic void
509649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Leviniterate(const char *const text, const int sig,
51c8cc0f2a87b5f7a33bf7dee39ba4ba2dc5cb4cb4Dmitry V. Levin	const void *const set, unsigned int size)
529649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin{
53c8cc0f2a87b5f7a33bf7dee39ba4ba2dc5cb4cb4Dmitry V. Levin	const void *mask;
54c8cc0f2a87b5f7a33bf7dee39ba4ba2dc5cb4cb4Dmitry V. Levin
55c8cc0f2a87b5f7a33bf7dee39ba4ba2dc5cb4cb4Dmitry V. Levin	for (mask = set;; size >>= 1, mask += size) {
569649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		raise(sig);
57c8cc0f2a87b5f7a33bf7dee39ba4ba2dc5cb4cb4Dmitry V. Levin		assert(k_sigsuspend(mask, size) == -1);
589649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		if (EINTR == errno) {
599649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin			tprintf("rt_sigsuspend(%s, %u) = ? ERESTARTNOHAND"
609649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin				" (To be restarted if no handler)\n",
619649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin				text, size);
629649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		} else {
639649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin			if (size < sizeof(long))
649649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin				tprintf("rt_sigsuspend(%p, %u)"
659649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin					" = -1 EINVAL (%m)\n",
66c8cc0f2a87b5f7a33bf7dee39ba4ba2dc5cb4cb4Dmitry V. Levin					mask, size);
679649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin			else
689649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin				tprintf("rt_sigsuspend(%s, %u)"
699649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin					" = -1 EINVAL (%m)\n",
70c8cc0f2a87b5f7a33bf7dee39ba4ba2dc5cb4cb4Dmitry V. Levin					set == mask ? text : "~[]", size);
719649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		}
729649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		if (!size)
739649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin			break;
749649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	}
759649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin}
769649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
779649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levinstatic void
789649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levinhandler(int signo)
799649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin{
809649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin}
819649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
829649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levinint
839649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levinmain(void)
849649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin{
859649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("%s", "");
869649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
879649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	const unsigned int big_size = 1024 / 8;
889649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	void *k_set = tail_alloc(big_size);
899649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	memset(k_set, 0, big_size);
909649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
919649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigset_t *const libc_set = tail_alloc(sizeof(sigset_t));
929649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigemptyset(libc_set);
939649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigaddset(libc_set, SIGUSR1);
949649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	if (sigprocmask(SIG_SETMASK, libc_set, NULL))
959649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		perror_msg_and_fail("sigprocmask");
969649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
979649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	const struct sigaction sa = {
989649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		.sa_handler = handler
999649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	};
1009649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	if (sigaction(SIGUSR1, &sa, NULL))
1019649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		perror_msg_and_fail("sigaction");
1029649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1039649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	raise(SIGUSR1);
1049649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	unsigned int set_size = big_size;
1059649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	for (; set_size; set_size >>= 1, k_set += set_size) {
1069649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		assert(k_sigsuspend(k_set, set_size) == -1);
1079649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		if (EINTR == errno)
1089649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin			break;
1099649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		tprintf("rt_sigsuspend(%p, %u) = -1 EINVAL (%m)\n",
1109649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin			k_set, set_size);
1119649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	}
1129649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	if (!set_size)
1139649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		perror_msg_and_fail("rt_sigsuspend");
1149649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("rt_sigsuspend([], %u) = ? ERESTARTNOHAND"
1159649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		" (To be restarted if no handler)\n", set_size);
1169649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1179649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigemptyset(libc_set);
1189649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigaddset(libc_set, SIGUSR2);
1199649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	memcpy(k_set, libc_set, set_size);
1209649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	raise(SIGUSR1);
1219649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(k_sigsuspend(k_set, set_size) == -1);
1229649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(EINTR == errno);
1239649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("rt_sigsuspend([USR2], %u) = ? ERESTARTNOHAND"
1249649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		" (To be restarted if no handler)\n", set_size);
1259649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1269649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigaddset(libc_set, SIGHUP);
1279649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	memcpy(k_set, libc_set, set_size);
1289649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	raise(SIGUSR1);
1299649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(k_sigsuspend(k_set, set_size) == -1);
1309649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(EINTR == errno);
1319649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("rt_sigsuspend([HUP USR2], %u) = ? ERESTARTNOHAND"
1329649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		" (To be restarted if no handler)\n", set_size);
1339649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1349649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigaddset(libc_set, SIGINT);
1359649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	memcpy(k_set, libc_set, set_size);
1369649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	raise(SIGUSR1);
1379649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(k_sigsuspend(k_set, set_size) == -1);
1389649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(EINTR == errno);
1399649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("rt_sigsuspend([HUP INT USR2], %u) = ? ERESTARTNOHAND"
1409649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		" (To be restarted if no handler)\n", set_size);
1419649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1429649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	memset(libc_set, -1, sizeof(*libc_set));
1439649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	sigdelset(libc_set, SIGUSR1);
1449649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	memcpy(k_set, libc_set, set_size);
1459649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	raise(SIGUSR1);
1469649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(k_sigsuspend(k_set, set_size) == -1);
1479649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(EINTR == errno);
1489649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("rt_sigsuspend(~[USR1], %u) = ? ERESTARTNOHAND"
1499649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		" (To be restarted if no handler)\n", set_size);
1509649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1519649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	assert(k_sigsuspend(k_set - set_size, set_size << 1) == -1);
1529649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("rt_sigsuspend(%p, %u) = -1 EINVAL (%m)\n",
1539649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin		k_set - set_size, set_size << 1);
1549649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1559649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	iterate("~[USR1]", SIGUSR1, k_set, set_size >> 1);
1569649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1579649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	tprintf("+++ exited with 0 +++\n");
1589649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin	return 0;
1599649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin}
1609649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1619649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin#else
1629649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1639649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. LevinSKIP_MAIN_UNDEFINED("__NR_rt_sigsuspend")
1649649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin
1659649ac1c8b5d217b82c818187bb476d8da2838f4Dmitry V. Levin#endif
166