1 /* Copyright (C) 2003-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
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
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <fcntl.h>
19 #include <pthread.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 
25 
26 static pthread_barrier_t b;
27 
28 
29 static void
cleanup(void * arg)30 cleanup (void *arg)
31 {
32   fputs ("in cleanup\n", stdout);
33 }
34 
35 
36 static void *
tf(void * arg)37 tf (void *arg)
38 {
39   int fd = open ("/dev/null", O_RDWR);
40   if (fd == -1)
41     {
42       puts ("cannot open /dev/null");
43       exit (1);
44     }
45   FILE *fp = fdopen (fd, "w");
46   if (fp == NULL)
47     {
48       puts ("fdopen failed");
49       exit (1);
50     }
51 
52   pthread_cleanup_push (cleanup, NULL);
53 
54   int e = pthread_barrier_wait (&b);
55   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
56     {
57       puts ("barrier_wait failed");
58       exit (1);
59     }
60 
61   while (1)
62     /* fprintf() uses write() which is a cancallation point.  */
63     fprintf (fp, "foo");
64 
65   pthread_cleanup_pop (0);
66 
67   return NULL;
68 }
69 
70 
71 static int
do_test(void)72 do_test (void)
73 {
74   if (pthread_barrier_init (&b, NULL, 2) != 0)
75     {
76       puts ("barrier_init failed");
77       exit (1);
78     }
79 
80   pthread_t th;
81   if (pthread_create (&th, NULL, tf, NULL) != 0)
82     {
83       puts ("create failed");
84       return 1;
85     }
86 
87   int e = pthread_barrier_wait (&b);
88   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
89     {
90       puts ("barrier_wait failed");
91       exit (1);
92     }
93 
94   sleep (1);
95 
96   puts ("cancel now");
97 
98   if (pthread_cancel (th) != 0)
99     {
100       puts ("cancel failed");
101       exit (1);
102     }
103 
104   puts ("waiting for the child");
105 
106   void *r;
107   if (pthread_join (th, &r) != 0)
108     {
109       puts ("join failed");
110       exit (1);
111     }
112 
113   if (r != PTHREAD_CANCELED)
114     {
115       puts ("thread wasn't canceled");
116       exit (1);
117     }
118 
119   return 0;
120 }
121 
122 
123 #define TEST_FUNCTION do_test ()
124 #include "../test-skeleton.c"
125