1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include "igt_core.h"
29 #include "drmtest.h"
30
31 #include "igt_tests_common.h"
32
33 int test;
34 int pipes[2];
35
exit_handler1(int sig)36 static void exit_handler1(int sig)
37 {
38 internal_assert(test == 1);
39 test++;
40 }
41
exit_handler2(int sig)42 static void exit_handler2(int sig)
43 {
44 char tmp = 1;
45
46 /* ensure exit handlers are called in reverse */
47 internal_assert(test == 0);
48 test++;
49
50 /* we need to get a side effect to the parent to make sure exit handlers
51 * actually run. */
52 internal_assert(write(pipes[1], &tmp, 1) == 1);
53 }
54
55 enum test_type {
56 SUC,
57 NORMAL,
58 FAIL,
59 SKIP,
60 SIG
61 };
62
testfunc(enum test_type test_type)63 static int testfunc(enum test_type test_type)
64 {
65 char prog[] = "igt_no_exit";
66 char *fake_argv[] = {prog};
67 int fake_argc = ARRAY_SIZE(fake_argv);
68 pid_t pid;
69 int status;
70 char tmp = 0;
71
72 internal_assert(pipe2(pipes, O_NONBLOCK) == 0);
73
74 pid = fork();
75
76 if (pid == 0) {
77 igt_subtest_init(fake_argc, fake_argv);
78
79 igt_fixture {
80 /* register twice, should only be called once */
81 igt_install_exit_handler(exit_handler1);
82 igt_install_exit_handler(exit_handler1);
83
84 igt_install_exit_handler(exit_handler2);
85 }
86
87 igt_subtest("subtest") {
88 switch (test_type) {
89 case SUC:
90 igt_success();
91 case FAIL:
92 igt_fail(1);
93 case SKIP:
94 igt_skip("skip");
95 case NORMAL:
96 break;
97 case SIG:
98 raise(SIGTERM);
99 }
100 }
101
102 igt_exit();
103 }
104
105 internal_assert(waitpid(pid, &status, 0) != -1);
106
107 internal_assert(read(pipes[0], &tmp, 1) == 1);
108 internal_assert(tmp == 1);
109
110 return status;
111 }
112
main(int argc,char ** argv)113 int main(int argc, char **argv)
114 {
115 int status;
116
117 internal_assert(testfunc(SUC) == 0);
118
119 internal_assert(testfunc(NORMAL) == 0);
120
121 status = testfunc(FAIL);
122 internal_assert_wexited(status, 1);
123
124 status = testfunc(SKIP);
125 internal_assert_wexited(status, IGT_EXIT_SKIP);
126
127 status = testfunc(SIG);
128 internal_assert_wsignaled(status, SIGTERM);
129 }
130