(root)/
strace-6.5/
tests-mx32/
wait4.c
       1  /*
       2   * Check decoding of wait4 syscall.
       3   *
       4   * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2020 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_wait4
      15  
      16  # include <assert.h>
      17  # include <signal.h>
      18  # include <stdio.h>
      19  # include <unistd.h>
      20  # include <sys/wait.h>
      21  # include "kernel_rusage.h"
      22  
      23  static const char *
      24  sprint_rusage(const kernel_rusage_t *const ru)
      25  {
      26  	static char buf[1024];
      27  	snprintf(buf, sizeof(buf),
      28  		 "{ru_utime={tv_sec=%llu, tv_usec=%llu}"
      29  		 ", ru_stime={tv_sec=%llu, tv_usec=%llu}"
      30  # if VERBOSE
      31  		 ", ru_maxrss=%llu"
      32  		 ", ru_ixrss=%llu"
      33  		 ", ru_idrss=%llu"
      34  		 ", ru_isrss=%llu"
      35  		 ", ru_minflt=%llu"
      36  		 ", ru_majflt=%llu"
      37  		 ", ru_nswap=%llu"
      38  		 ", ru_inblock=%llu"
      39  		 ", ru_oublock=%llu"
      40  		 ", ru_msgsnd=%llu"
      41  		 ", ru_msgrcv=%llu"
      42  		 ", ru_nsignals=%llu"
      43  		 ", ru_nvcsw=%llu"
      44  		 ", ru_nivcsw=%llu}"
      45  # else
      46  		 ", ...}"
      47  # endif
      48  		 , zero_extend_signed_to_ull(ru->ru_utime.tv_sec)
      49  		 , zero_extend_signed_to_ull(ru->ru_utime.tv_usec)
      50  		 , zero_extend_signed_to_ull(ru->ru_stime.tv_sec)
      51  		 , zero_extend_signed_to_ull(ru->ru_stime.tv_usec)
      52  # if VERBOSE
      53  		 , zero_extend_signed_to_ull(ru->ru_maxrss)
      54  		 , zero_extend_signed_to_ull(ru->ru_ixrss)
      55  		 , zero_extend_signed_to_ull(ru->ru_idrss)
      56  		 , zero_extend_signed_to_ull(ru->ru_isrss)
      57  		 , zero_extend_signed_to_ull(ru->ru_minflt)
      58  		 , zero_extend_signed_to_ull(ru->ru_majflt)
      59  		 , zero_extend_signed_to_ull(ru->ru_nswap)
      60  		 , zero_extend_signed_to_ull(ru->ru_inblock)
      61  		 , zero_extend_signed_to_ull(ru->ru_oublock)
      62  		 , zero_extend_signed_to_ull(ru->ru_msgsnd)
      63  		 , zero_extend_signed_to_ull(ru->ru_msgrcv)
      64  		 , zero_extend_signed_to_ull(ru->ru_nsignals)
      65  		 , zero_extend_signed_to_ull(ru->ru_nvcsw)
      66  		 , zero_extend_signed_to_ull(ru->ru_nivcsw)
      67  # endif
      68  		 );
      69  	return buf;
      70  }
      71  
      72  static const char *errstr;
      73  
      74  static long
      75  k_wait4(const unsigned int pid, void const *wstatus,
      76  	const unsigned int options, void const *ru)
      77  {
      78  	const kernel_ulong_t fill = (kernel_ulong_t) 0xdefaced00000000ULL;
      79  	const kernel_ulong_t bad = (kernel_ulong_t) 0xbadc0dedbadc0dedULL;
      80  	const kernel_ulong_t arg1 = fill | pid;
      81  	const kernel_ulong_t arg2 = (uintptr_t) wstatus;
      82  	const kernel_ulong_t arg3 = fill | options;
      83  	const kernel_ulong_t arg4 = (uintptr_t) ru;
      84  	const long rc = syscall(__NR_wait4, arg1, arg2, arg3, arg4, bad, bad);
      85  	errstr = sprintrc(rc);
      86  	return rc;
      87  }
      88  
      89  static pid_t
      90  do_wait4(pid_t pid, int *wstatus, int options, kernel_rusage_t *ru)
      91  {
      92  	sigset_t mask = {};
      93  	sigaddset(&mask, SIGCHLD);
      94  
      95  	assert(sigprocmask(SIG_BLOCK, &mask, NULL) == 0);
      96  	pid_t rc = k_wait4(pid, wstatus, options, ru);
      97  	assert(sigprocmask(SIG_UNBLOCK, &mask, NULL) == 0);
      98  	return rc;
      99  }
     100  
     101  int
     102  main(void)
     103  {
     104  	tprintf("%s", "");
     105  
     106  	int fds[2];
     107  	if (pipe(fds))
     108  		perror_msg_and_fail("pipe");
     109  
     110  	pid_t pid;
     111  	pid = fork();
     112  	if (pid < 0)
     113  		perror_msg_and_fail("fork");
     114  
     115  	if (!pid) {
     116  		char c;
     117  		(void) close(1);
     118  		assert(read(0, &c, sizeof(c)) == 1);
     119  		return 42;
     120  	}
     121  
     122  	(void) close(0);
     123  
     124  	TAIL_ALLOC_OBJECT_CONST_PTR(int, s);
     125  	if (k_wait4(pid, s, WNOHANG|__WALL, NULL))
     126  		perror_msg_and_fail("wait4 #1");
     127  	tprintf("wait4(%d, %p, WNOHANG|__WALL, NULL) = 0\n", pid, s);
     128  
     129  	TAIL_ALLOC_OBJECT_CONST_PTR(kernel_rusage_t, rusage);
     130  	if (k_wait4(pid, s, WNOHANG|__WALL, rusage))
     131  		perror_msg_and_fail("wait4 #2");
     132  	tprintf("wait4(%d, %p, WNOHANG|__WALL, %p) = 0\n", pid, s, rusage);
     133  
     134  	assert(write(1, "", 1) == 1);
     135  	(void) close(1);
     136  
     137  	assert(do_wait4(pid, s, 0, rusage) == pid);
     138  	assert(WIFEXITED(*s) && WEXITSTATUS(*s) == 42);
     139  	tprintf("wait4(%d, [{WIFEXITED(s) && WEXITSTATUS(s) == 42}], 0, %s)"
     140  		" = %d\n", pid, sprint_rusage(rusage), pid);
     141  
     142  	pid = fork();
     143  	if (pid < 0)
     144  		perror_msg_and_fail("fork");
     145  
     146  	if (!pid) {
     147  		(void) raise(SIGUSR1);
     148  		return 1;
     149  	}
     150  
     151  	assert(do_wait4(pid, s, __WALL, rusage) == pid);
     152  	assert(WIFSIGNALED(*s) && WTERMSIG(*s) == SIGUSR1);
     153  	tprintf("wait4(%d, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGUSR1}]"
     154  		", __WALL, %s) = %d\n", pid, sprint_rusage(rusage), pid);
     155  
     156  	if (pipe(fds))
     157  		perror_msg_and_fail("pipe");
     158  	pid = fork();
     159  	if (pid < 0)
     160  		perror_msg_and_fail("fork");
     161  
     162  	if (!pid) {
     163  		(void) close(1);
     164  		raise(SIGSTOP);
     165  		char c;
     166  		assert(read(0, &c, sizeof(c)) == 1);
     167  		return 0;
     168  	}
     169  
     170  	(void) close(0);
     171  
     172  	assert(do_wait4(pid, s, WSTOPPED, rusage) == pid);
     173  	assert(WIFSTOPPED(*s) && WSTOPSIG(*s) == SIGSTOP);
     174  	tprintf("wait4(%d, [{WIFSTOPPED(s) && WSTOPSIG(s) == SIGSTOP}]"
     175  		", WSTOPPED, %s) = %d\n", pid, sprint_rusage(rusage), pid);
     176  
     177  	if (kill(pid, SIGCONT))
     178  		perror_msg_and_fail("kill(SIGCONT)");
     179  
     180  # if defined WCONTINUED && defined WIFCONTINUED
     181  	assert(do_wait4(pid, s, WCONTINUED, rusage) == pid);
     182  	assert(WIFCONTINUED(*s));
     183  	tprintf("wait4(%d, [{WIFCONTINUED(s)}], WCONTINUED"
     184  		", %s) = %d\n", pid, sprint_rusage(rusage), pid);
     185  # endif /* WCONTINUED && WIFCONTINUED */
     186  
     187  	assert(write(1, "", 1) == 1);
     188  	(void) close(1);
     189  
     190  	assert(do_wait4(pid, s, 0, rusage) == pid);
     191  	assert(WIFEXITED(*s) && WEXITSTATUS(*s) == 0);
     192  	tprintf("wait4(%d, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0"
     193  		", %s) = %d\n", pid, sprint_rusage(rusage), pid);
     194  
     195  	assert(k_wait4(-1, s, WNOHANG|WSTOPPED|__WALL, rusage) == -1);
     196  	tprintf("wait4(-1, %p, WNOHANG|WSTOPPED|__WALL, %p) = %s\n",
     197  		s, rusage, errstr);
     198  
     199  	tprintf("%s\n", "+++ exited with 0 +++");
     200  	return 0;
     201  }
     202  
     203  #else
     204  
     205  SKIP_MAIN_UNDEFINED("__NR_wait4")
     206  
     207  #endif /* __NR_wait4 */