about summary refs log tree commit diff
path: root/signal/tst-sigwait-eintr.c
blob: e28e05bac51a5682896c9ba8b8a14f6129fbf1ba (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/* Check that sigwait does not fail with EINTR (bug 22478).
   Copyright (C) 2017-2020 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
   <https://www.gnu.org/licenses/>.  */

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <support/check.h>
#include <support/xunistd.h>
#include <time.h>
#include <unistd.h>

/* Handler for SIGUSR1.  */
static void
sigusr1_handler (int signo)
{
  TEST_VERIFY (signo == SIGUSR1);
}

/* Spawn a subprocess to send two signals: First SIGUSR1, then
   SIGUSR2.  Return the PID of the process.  */
static pid_t
signal_sender (void)
{
  pid_t pid = xfork ();
  if (pid == 0)
    {
      static const struct timespec delay = { 1, };
      if (nanosleep (&delay, NULL) != 0)
        FAIL_EXIT1 ("nanosleep: %m");
      if (kill (getppid (), SIGUSR1) != 0)
        FAIL_EXIT1 ("kill (SIGUSR1): %m");
      if (nanosleep (&delay, NULL) != 0)
        FAIL_EXIT1 ("nanosleep: %m");
      if (kill (getppid (), SIGUSR2) != 0)
        FAIL_EXIT1 ("kill (SIGUSR2): %m");
      _exit (0);
    }
  return pid;
}

static int
do_test (void)
{
  if (signal (SIGUSR1, sigusr1_handler) == SIG_ERR)
    FAIL_EXIT1 ("signal (SIGUSR1): %m\n");

  sigset_t sigs;
  sigemptyset (&sigs);
  sigaddset (&sigs, SIGUSR2);
  if (sigprocmask (SIG_BLOCK, &sigs, NULL) != 0)
    FAIL_EXIT1 ("sigprocmask (SIGBLOCK, SIGUSR2): %m");
  pid_t pid = signal_sender ();
  int signo = 0;
  int ret = sigwait (&sigs, &signo);
  if (ret != 0)
    {
      support_record_failure ();
      errno = ret;
      printf ("error: sigwait failed: %m (%d)\n", ret);
    }
  TEST_VERIFY (signo == SIGUSR2);

  int status;
  xwaitpid (pid, &status, 0);
  TEST_VERIFY (status == 0);

  return 0;
}

#include <support/test-driver.c>