(root)/
strace-6.5/
tests/
rt_sigtimedwait.c
       1  /*
       2   * This file is part of rt_sigtimedwait strace test.
       3   *
       4   * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2023 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include "scno.h"
      13  
      14  #ifdef __NR_rt_sigtimedwait
      15  
      16  # include <assert.h>
      17  # include <errno.h>
      18  # include <signal.h>
      19  # include <stdio.h>
      20  # include <stdint.h>
      21  # include <string.h>
      22  # include <unistd.h>
      23  
      24  static long
      25  k_sigtimedwait(const sigset_t *const set, siginfo_t *const info,
      26  	       const kernel_old_timespec_t *const timeout, const unsigned long size)
      27  {
      28  	return syscall(__NR_rt_sigtimedwait, set, info, timeout, size);
      29  }
      30  
      31  static void
      32  iterate(const char *const text, const void *set,
      33  	const kernel_old_timespec_t *const timeout, unsigned int size)
      34  {
      35  	for (;;) {
      36  		assert(k_sigtimedwait(set, NULL, timeout, size) == -1);
      37  		if (EINTR == errno) {
      38  			tprintf("rt_sigtimedwait(%s, NULL"
      39  				", {tv_sec=%lld, tv_nsec=%llu}, %u)"
      40  				" = -1 EAGAIN (%m)\n", text,
      41  				(long long) timeout->tv_sec,
      42  				zero_extend_signed_to_ull(timeout->tv_nsec),
      43  				size);
      44  		} else {
      45  			if (size < sizeof(long))
      46  				tprintf("rt_sigtimedwait(%p, NULL"
      47  					", {tv_sec=%lld, tv_nsec=%llu}"
      48  					", %u) = -1 EINVAL (%m)\n",
      49  					set, (long long) timeout->tv_sec,
      50  					zero_extend_signed_to_ull(timeout->tv_nsec),
      51  					size);
      52  			else
      53  				tprintf("rt_sigtimedwait(%s, NULL"
      54  					", {tv_sec=%lld, tv_nsec=%llu}"
      55  					", %u) = -1 EINVAL (%m)\n",
      56  					text, (long long) timeout->tv_sec,
      57  					zero_extend_signed_to_ull(timeout->tv_nsec),
      58  					size);
      59  		}
      60  		if (!size)
      61  			break;
      62  		size >>= 1;
      63  		set += size;
      64  	}
      65  }
      66  
      67  int
      68  main(void)
      69  {
      70  	tprintf("%s", "");
      71  
      72  	TAIL_ALLOC_OBJECT_CONST_PTR(siginfo_t, info);
      73  	TAIL_ALLOC_OBJECT_CONST_PTR(kernel_old_timespec_t, timeout);
      74  	timeout->tv_sec = 0;
      75  	timeout->tv_nsec = 42;
      76  
      77  	const unsigned int big_size = 1024 / 8;
      78  	void *k_set = tail_alloc(big_size);
      79  	memset(k_set, 0, big_size);
      80  
      81  	unsigned int set_size = big_size;
      82  	for (; set_size; set_size >>= 1, k_set += set_size) {
      83  		assert(k_sigtimedwait(k_set, NULL, timeout, set_size) == -1);
      84  		if (EAGAIN == errno)
      85  			break;
      86  		tprintf("rt_sigtimedwait(%p, NULL, {tv_sec=%lld, tv_nsec=%llu}"
      87  			", %u) = -1 EINVAL (%m)\n",
      88  			k_set, (long long) timeout->tv_sec,
      89  			zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
      90  	}
      91  	if (!set_size)
      92  		perror_msg_and_fail("rt_sigtimedwait");
      93  	tprintf("rt_sigtimedwait([], NULL, {tv_sec=%lld, tv_nsec=%llu}, %u)"
      94  		" = -1 EAGAIN (%m)\n",
      95  		(long long) timeout->tv_sec,
      96  		zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
      97  
      98  	timeout->tv_sec = 0xdeadbeefU;
      99  	timeout->tv_nsec = 0xfacefeedU;
     100  	assert(k_sigtimedwait(k_set, NULL, timeout, set_size) == -1);
     101  	tprintf("rt_sigtimedwait([], NULL, {tv_sec=%lld, tv_nsec=%llu}"
     102  		", %u) = -1 EINVAL (%m)\n",
     103  		(long long) timeout->tv_sec,
     104  		zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
     105  
     106  	timeout->tv_sec = (typeof(timeout->tv_sec)) 0xcafef00ddeadbeefLL;
     107  	timeout->tv_nsec = (long) 0xbadc0dedfacefeedLL;
     108  	assert(k_sigtimedwait(k_set, NULL, timeout, set_size) == -1);
     109  	tprintf("rt_sigtimedwait([], NULL, {tv_sec=%lld, tv_nsec=%llu}"
     110  		", %u) = -1 EINVAL (%m)\n",
     111  		(long long) timeout->tv_sec,
     112  		zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
     113  
     114  	timeout->tv_sec = 0;
     115  	timeout->tv_nsec = 42;
     116  
     117  	TAIL_ALLOC_OBJECT_CONST_PTR(sigset_t, libc_set);
     118  	sigemptyset(libc_set);
     119  	sigaddset(libc_set, SIGHUP);
     120  	memcpy(k_set, libc_set, set_size);
     121  
     122  	assert(k_sigtimedwait(k_set, info, timeout, set_size) == -1);
     123  	assert(EAGAIN == errno);
     124  	tprintf("rt_sigtimedwait([HUP], %p, {tv_sec=%lld, tv_nsec=%llu}, %u)"
     125  		" = -1 EAGAIN (%m)\n",
     126  		info, (long long) timeout->tv_sec,
     127  		zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
     128  
     129  	sigaddset(libc_set, SIGINT);
     130  	memcpy(k_set, libc_set, set_size);
     131  
     132  	assert(k_sigtimedwait(k_set, info, timeout, set_size) == -1);
     133  	assert(EAGAIN == errno);
     134  	tprintf("rt_sigtimedwait([HUP INT], %p, {tv_sec=%lld, tv_nsec=%llu}, %u)"
     135  		" = -1 EAGAIN (%m)\n",
     136  		info, (long long) timeout->tv_sec,
     137  		zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
     138  
     139  	sigaddset(libc_set, SIGQUIT);
     140  	sigaddset(libc_set, SIGALRM);
     141  	sigaddset(libc_set, SIGTERM);
     142  	memcpy(k_set, libc_set, set_size);
     143  
     144  	assert(k_sigtimedwait(k_set, info, timeout, set_size) == -1);
     145  	assert(EAGAIN == errno);
     146  	tprintf("rt_sigtimedwait(%s, %p, {tv_sec=%lld, tv_nsec=%llu}, %u)"
     147  		" = -1 EAGAIN (%m)\n",
     148  		"[HUP INT QUIT ALRM TERM]",
     149  		info, (long long) timeout->tv_sec,
     150  		zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
     151  
     152  	memset(k_set - set_size, -1, set_size);
     153  	assert(k_sigtimedwait(k_set - set_size, info, timeout, set_size) == -1);
     154  	assert(EAGAIN == errno);
     155  	tprintf("rt_sigtimedwait(~[], %p, {tv_sec=%lld, tv_nsec=%llu}, %u)"
     156  		" = -1 EAGAIN (%m)\n",
     157  		info, (long long) timeout->tv_sec,
     158  		zero_extend_signed_to_ull(timeout->tv_nsec), set_size);
     159  
     160  	if (sigprocmask(SIG_SETMASK, libc_set, NULL))
     161  		perror_msg_and_fail("sigprocmask");
     162  
     163  	assert(k_sigtimedwait(k_set - set_size, info, NULL, set_size << 1) == -1);
     164  	tprintf("rt_sigtimedwait(%p, %p, NULL, %u) = -1 EINVAL (%m)\n",
     165  		k_set - set_size, info, set_size << 1);
     166  
     167  	iterate("~[]", k_set - set_size, timeout, set_size >> 1);
     168  
     169  	timeout->tv_sec = 1;
     170  	raise(SIGALRM);
     171  	assert(k_sigtimedwait(k_set, info, timeout, set_size) == SIGALRM);
     172  	tprintf("rt_sigtimedwait(%s, {si_signo=%s, si_code=SI_TKILL"
     173  		", si_pid=%d, si_uid=%d}, {tv_sec=%lld, tv_nsec=%llu}, %u)"
     174  		" = %d (%s)\n",
     175  		"[HUP INT QUIT ALRM TERM]", "SIGALRM", getpid(), getuid(),
     176  		(long long) timeout->tv_sec,
     177  		zero_extend_signed_to_ull(timeout->tv_nsec),
     178  		set_size, SIGALRM, "SIGALRM");
     179  
     180  	raise(SIGALRM);
     181  	assert(k_sigtimedwait(k_set, NULL, NULL, set_size) == SIGALRM);
     182  	tprintf("rt_sigtimedwait(%s, NULL, NULL, %u) = %d (%s)\n",
     183  		"[HUP INT QUIT ALRM TERM]", set_size, SIGALRM, "SIGALRM");
     184  
     185  	tprintf("+++ exited with 0 +++\n");
     186  	return 0;
     187  }
     188  
     189  #else
     190  
     191  SKIP_MAIN_UNDEFINED("__NR_rt_sigtimedwait")
     192  
     193  #endif