]>
Commit | Line | Data |
---|---|---|
dff8da6b | 1 | /* Copyright (C) 2002-2024 Free Software Foundation, Inc. |
b74121ae | 2 | This file is part of the GNU C Library. |
b74121ae UD |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
b74121ae UD |
17 | |
18 | #include <errno.h> | |
19 | #include <fcntl.h> | |
6f4973c1 | 20 | #include <getopt.h> |
b74121ae | 21 | #include <signal.h> |
b74121ae | 22 | #include <stdlib.h> |
6f4973c1 AZ |
23 | #include <semaphore.h> |
24 | #include <sys/mman.h> | |
25 | ||
26 | #include <support/check.h> | |
27 | #include <support/support.h> | |
28 | #include <support/temp_file.h> | |
29 | #include <support/xstdio.h> | |
30 | #include <support/xunistd.h> | |
c23de0aa | 31 | #include <support/xthread.h> |
b74121ae | 32 | |
6f4973c1 AZ |
33 | static const char *command; |
34 | static const char *pidfile; | |
35 | static const char *semfile; | |
36 | static char *pidfilename; | |
37 | static char *semfilename; | |
38 | ||
39 | static sem_t *sem; | |
b74121ae UD |
40 | |
41 | static void * | |
42 | tf (void *arg) | |
43 | { | |
6f4973c1 AZ |
44 | char *cmd = xasprintf ("%s --direct --sem %s --pidfile %s", |
45 | command, semfilename, pidfilename); | |
8022fc7d FB |
46 | if (system (cmd)) |
47 | FAIL_EXIT1("system call unexpectedly returned"); | |
b74121ae UD |
48 | /* This call should never return. */ |
49 | return NULL; | |
50 | } | |
51 | ||
b74121ae UD |
52 | static void |
53 | sl (void) | |
54 | { | |
6f4973c1 | 55 | FILE *f = xfopen (pidfile, "w"); |
b74121ae UD |
56 | |
57 | fprintf (f, "%lld\n", (long long) getpid ()); | |
58 | fflush (f); | |
59 | ||
6f4973c1 AZ |
60 | if (sem_post (sem) != 0) |
61 | FAIL_EXIT1 ("sem_post: %m"); | |
62 | ||
b74121ae UD |
63 | struct flock fl = |
64 | { | |
65 | .l_type = F_WRLCK, | |
66 | .l_start = 0, | |
67 | .l_whence = SEEK_SET, | |
68 | .l_len = 1 | |
69 | }; | |
70 | if (fcntl (fileno (f), F_SETLK, &fl) != 0) | |
6f4973c1 | 71 | FAIL_EXIT1 ("fcntl (F_SETFL): %m"); |
b74121ae UD |
72 | |
73 | sigset_t ss; | |
74 | sigfillset (&ss); | |
75 | sigsuspend (&ss); | |
76 | exit (0); | |
77 | } | |
78 | ||
79 | ||
80 | static void | |
81 | do_prepare (int argc, char *argv[]) | |
82 | { | |
6f4973c1 AZ |
83 | int semfd; |
84 | if (semfile == NULL) | |
85 | semfd = create_temp_file ("tst-cancel7.", &semfilename); | |
86 | else | |
87 | semfd = open (semfile, O_RDWR); | |
88 | TEST_VERIFY_EXIT (semfd != -1); | |
89 | ||
90 | sem = xmmap (NULL, sizeof (sem_t), PROT_READ | PROT_WRITE, MAP_SHARED, | |
91 | semfd); | |
92 | TEST_VERIFY_EXIT (sem != SEM_FAILED); | |
93 | if (semfile == NULL) | |
94 | { | |
95 | xftruncate (semfd, sizeof (sem_t)); | |
96 | TEST_VERIFY_EXIT (sem_init (sem, 1, 0) != -1); | |
97 | } | |
98 | ||
b74121ae UD |
99 | if (command == NULL) |
100 | command = argv[0]; | |
101 | ||
102 | if (pidfile) | |
103 | sl (); | |
104 | ||
6f4973c1 | 105 | int fd = create_temp_file ("tst-cancel7-pid-", &pidfilename); |
b74121ae | 106 | if (fd == -1) |
6f4973c1 | 107 | FAIL_EXIT1 ("create_temp_file failed: %m"); |
b74121ae | 108 | |
6f4973c1 AZ |
109 | xwrite (fd, " ", 1); |
110 | xclose (fd); | |
b74121ae UD |
111 | } |
112 | ||
113 | ||
114 | static int | |
115 | do_test (void) | |
116 | { | |
6f4973c1 | 117 | pthread_t th = xpthread_create (NULL, tf, NULL); |
b74121ae | 118 | |
06acd6d1 SH |
119 | /* Wait to cancel until after the pid is written. */ |
120 | if (sem_wait (sem) != 0) | |
121 | FAIL_EXIT1 ("sem_wait: %m"); | |
b74121ae | 122 | |
c23de0aa FW |
123 | xpthread_cancel (th); |
124 | void *r = xpthread_join (th); | |
b74121ae | 125 | |
6f4973c1 | 126 | FILE *f = xfopen (pidfilename, "r+"); |
b74121ae UD |
127 | |
128 | long long ll; | |
129 | if (fscanf (f, "%lld\n", &ll) != 1) | |
6f4973c1 | 130 | FAIL_EXIT1 ("fscanf: %m"); |
b74121ae UD |
131 | |
132 | struct flock fl = | |
133 | { | |
134 | .l_type = F_WRLCK, | |
135 | .l_start = 0, | |
136 | .l_whence = SEEK_SET, | |
137 | .l_len = 1 | |
138 | }; | |
139 | if (fcntl (fileno (f), F_GETLK, &fl) != 0) | |
6f4973c1 | 140 | FAIL_EXIT1 ("fcntl: %m"); |
b74121ae UD |
141 | |
142 | if (fl.l_type != F_UNLCK) | |
143 | { | |
144 | printf ("child %lld still running\n", (long long) fl.l_pid); | |
145 | if (fl.l_pid == ll) | |
146 | kill (fl.l_pid, SIGKILL); | |
147 | ||
b74121ae UD |
148 | return 1; |
149 | } | |
150 | ||
6f4973c1 | 151 | xfclose (f); |
b74121ae UD |
152 | |
153 | return r != PTHREAD_CANCELED; | |
154 | } | |
155 | ||
156 | static void | |
157 | do_cleanup (void) | |
158 | { | |
159 | FILE *f = fopen (pidfilename, "r+"); | |
160 | long long ll; | |
161 | ||
162 | if (f != NULL && fscanf (f, "%lld\n", &ll) == 1) | |
163 | { | |
164 | struct flock fl = | |
165 | { | |
166 | .l_type = F_WRLCK, | |
167 | .l_start = 0, | |
168 | .l_whence = SEEK_SET, | |
169 | .l_len = 1 | |
170 | }; | |
171 | if (fcntl (fileno (f), F_GETLK, &fl) == 0 && fl.l_type != F_UNLCK | |
172 | && fl.l_pid == ll) | |
173 | kill (fl.l_pid, SIGKILL); | |
174 | ||
175 | fclose (f); | |
176 | } | |
b74121ae UD |
177 | } |
178 | ||
179 | #define OPT_COMMAND 10000 | |
180 | #define OPT_PIDFILE 10001 | |
6f4973c1 | 181 | #define OPT_SEMFILE 10002 |
b74121ae UD |
182 | #define CMDLINE_OPTIONS \ |
183 | { "command", required_argument, NULL, OPT_COMMAND }, \ | |
6f4973c1 AZ |
184 | { "pidfile", required_argument, NULL, OPT_PIDFILE }, \ |
185 | { "sem", required_argument, NULL, OPT_SEMFILE }, | |
c23de0aa FW |
186 | static void |
187 | cmdline_process (int c) | |
188 | { | |
189 | switch (c) | |
190 | { | |
f38aee21 | 191 | case OPT_COMMAND: |
c23de0aa FW |
192 | command = optarg; |
193 | break; | |
194 | case OPT_PIDFILE: | |
195 | pidfile = optarg; | |
196 | break; | |
6f4973c1 AZ |
197 | case OPT_SEMFILE: |
198 | semfile = optarg; | |
199 | break; | |
c23de0aa FW |
200 | } |
201 | } | |
202 | #define CMDLINE_PROCESS cmdline_process | |
203 | #define CLEANUP_HANDLER do_cleanup | |
204 | #define PREPARE do_prepare | |
c23de0aa | 205 | #include <support/test-driver.c> |