build-many-glibcs.py: Add openrisc hard float glibc variant
[glibc.git] / nptl / tst-cancel7.c
blobd2350bde2043ae403a1e825a8e9a057fc7f156c4
1 /* Copyright (C) 2002-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <getopt.h>
21 #include <signal.h>
22 #include <stdlib.h>
23 #include <semaphore.h>
24 #include <sys/mman.h>
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>
31 #include <support/xthread.h>
33 static const char *command;
34 static const char *pidfile;
35 static const char *semfile;
36 static char *pidfilename;
37 static char *semfilename;
39 static sem_t *sem;
41 static void *
42 tf (void *arg)
44 char *cmd = xasprintf ("%s --direct --sem %s --pidfile %s",
45 command, semfilename, pidfilename);
46 if (system (cmd))
47 FAIL_EXIT1("system call unexpectedly returned");
48 /* This call should never return. */
49 return NULL;
52 static void
53 sl (void)
55 FILE *f = xfopen (pidfile, "w");
57 fprintf (f, "%lld\n", (long long) getpid ());
58 fflush (f);
60 if (sem_post (sem) != 0)
61 FAIL_EXIT1 ("sem_post: %m");
63 struct flock fl =
65 .l_type = F_WRLCK,
66 .l_start = 0,
67 .l_whence = SEEK_SET,
68 .l_len = 1
70 if (fcntl (fileno (f), F_SETLK, &fl) != 0)
71 FAIL_EXIT1 ("fcntl (F_SETFL): %m");
73 sigset_t ss;
74 sigfillset (&ss);
75 sigsuspend (&ss);
76 exit (0);
80 static void
81 do_prepare (int argc, char *argv[])
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);
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)
95 xftruncate (semfd, sizeof (sem_t));
96 TEST_VERIFY_EXIT (sem_init (sem, 1, 0) != -1);
99 if (command == NULL)
100 command = argv[0];
102 if (pidfile)
103 sl ();
105 int fd = create_temp_file ("tst-cancel7-pid-", &pidfilename);
106 if (fd == -1)
107 FAIL_EXIT1 ("create_temp_file failed: %m");
109 xwrite (fd, " ", 1);
110 xclose (fd);
114 static int
115 do_test (void)
117 pthread_t th = xpthread_create (NULL, tf, NULL);
119 /* Wait to cancel until after the pid is written. */
120 if (sem_wait (sem) != 0)
121 FAIL_EXIT1 ("sem_wait: %m");
123 xpthread_cancel (th);
124 void *r = xpthread_join (th);
126 FILE *f = xfopen (pidfilename, "r+");
128 long long ll;
129 if (fscanf (f, "%lld\n", &ll) != 1)
130 FAIL_EXIT1 ("fscanf: %m");
132 struct flock fl =
134 .l_type = F_WRLCK,
135 .l_start = 0,
136 .l_whence = SEEK_SET,
137 .l_len = 1
139 if (fcntl (fileno (f), F_GETLK, &fl) != 0)
140 FAIL_EXIT1 ("fcntl: %m");
142 if (fl.l_type != F_UNLCK)
144 printf ("child %lld still running\n", (long long) fl.l_pid);
145 if (fl.l_pid == ll)
146 kill (fl.l_pid, SIGKILL);
148 return 1;
151 xfclose (f);
153 return r != PTHREAD_CANCELED;
156 static void
157 do_cleanup (void)
159 FILE *f = fopen (pidfilename, "r+");
160 long long ll;
162 if (f != NULL && fscanf (f, "%lld\n", &ll) == 1)
164 struct flock fl =
166 .l_type = F_WRLCK,
167 .l_start = 0,
168 .l_whence = SEEK_SET,
169 .l_len = 1
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);
175 fclose (f);
179 #define OPT_COMMAND 10000
180 #define OPT_PIDFILE 10001
181 #define OPT_SEMFILE 10002
182 #define CMDLINE_OPTIONS \
183 { "command", required_argument, NULL, OPT_COMMAND }, \
184 { "pidfile", required_argument, NULL, OPT_PIDFILE }, \
185 { "sem", required_argument, NULL, OPT_SEMFILE },
186 static void
187 cmdline_process (int c)
189 switch (c)
191 case OPT_COMMAND:
192 command = optarg;
193 break;
194 case OPT_PIDFILE:
195 pidfile = optarg;
196 break;
197 case OPT_SEMFILE:
198 semfile = optarg;
199 break;
202 #define CMDLINE_PROCESS cmdline_process
203 #define CLEANUP_HANDLER do_cleanup
204 #define PREPARE do_prepare
205 #include <support/test-driver.c>