File: test_sigstate.c

package info (click to toggle)
util-linux 2.41.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 92,844 kB
  • sloc: ansic: 179,146; sh: 22,716; yacc: 1,284; makefile: 525; xml: 422; python: 316; lex: 89; ruby: 75; csh: 37; exp: 19; sed: 16; perl: 15; sql: 9
file content (95 lines) | stat: -rw-r--r-- 1,991 bytes parent folder | download | duplicates (3)
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
86
87
88
89
90
91
92
93
94
95
/*
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * test_sigstate - ...
 *
 * Written by Masatake YAMATO <yamato@redhat.com>
 */

#include "c.h"

#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <err.h>

#define _U_ __attribute__((__unused__))

static enum {
	HANDLER_NONE,
	HANDLER_WRITE,
	HANDLER_READ
} handler_state = HANDLER_NONE;

static int ERRNO;

static void handler(int signum _U_)
{
	char c;

	if (write(1, "USR1\n", 5) == -1) {
		handler_state = HANDLER_WRITE;
		goto out;
	}

	if (read(0, &c, 1) != -1)
		_exit(0);
	handler_state = HANDLER_READ;

 out:
	ERRNO = errno;
}

int main(int argc _U_, char **argv _U_)
{
	sigset_t block_set;

	sigemptyset(&block_set);
	sigaddset(&block_set, SIGINT);
	sigaddset(&block_set, SIGILL);
	sigaddset(&block_set, SIGABRT);
	sigaddset(&block_set, SIGFPE);
	sigaddset(&block_set, SIGSEGV);
	sigaddset(&block_set, SIGTERM);

	if (sigprocmask(SIG_SETMASK, &block_set, NULL) == -1)
		err(EXIT_FAILURE, "failed to mask signals");

	raise(SIGINT);
	raise(SIGILL);

#define sigignore(S) if (signal(S, SIG_IGN) == SIG_ERR) \
		err(EXIT_FAILURE, "failed to make " #S "ignored")

	sigignore(SIGHUP);
	sigignore(SIGQUIT);
	sigignore(SIGTRAP);
	sigignore(SIGPIPE);
	sigignore(SIGALRM);

	signal(SIGINT, SIG_DFL);
	signal(SIGBUS, SIG_DFL);
	signal(SIGFPE, SIG_DFL);
	signal(SIGSEGV, SIG_DFL);
	signal(32, SIG_DFL);
	signal(33, SIG_DFL);

	if (signal(SIGUSR1, handler) == SIG_ERR)
		err(EXIT_FAILURE, "failed to set a signal handler for SIGUSR1");
	if (signal(SIGILL, handler) == SIG_ERR)
		err(EXIT_FAILURE, "failed to set a signal handler for SIGILL");

	printf("%d\n", getpid());
	if (fflush(stdout) == EOF)
		err(EXIT_FAILURE, "failed to flush stdout");

	pause();
	if (ERRNO == 0)
		errx(EXIT_FAILURE, "caught an unexpected signal");
	errno = ERRNO;
	errx(EXIT_FAILURE, "failed in %s an ack from the command invoker",
	     handler_state == HANDLER_WRITE? "writing": "reading");

	return 0;		/* UNREACHABLE */
}