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 <errno.h>
19 #include <pthread.h>
20 #include <signal.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 
26 
27 static int do_test (void);
28 
29 #define TEST_FUNCTION do_test ()
30 #include "../test-skeleton.c"
31 
32 static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
33 static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
34 static pthread_barrier_t b;
35 
36 
37 static void
handler(int sig)38 handler (int sig)
39 {
40   write_message ("handler called\n");
41   _exit (1);
42 }
43 
44 
45 static void *
tf(void * a)46 tf (void *a)
47 {
48   /* Block SIGUSR1.  */
49   sigset_t ss;
50 
51   sigemptyset (&ss);
52   sigaddset (&ss, SIGUSR1);
53   if (pthread_sigmask (SIG_BLOCK, &ss, NULL) != 0)
54     {
55       puts ("child: sigmask failed");
56       exit (1);
57     }
58 
59   if (pthread_mutex_lock (&m) != 0)
60     {
61       puts ("child: mutex_lock failed");
62       exit (1);
63     }
64 
65   int e = pthread_barrier_wait (&b);
66   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
67     {
68       puts ("child: barrier_wait failed");
69       exit (1);
70     }
71 
72   /* Compute timeout.  */
73   struct timeval tv;
74   (void) gettimeofday (&tv, NULL);
75   struct timespec ts;
76   TIMEVAL_TO_TIMESPEC (&tv, &ts);
77   /* Timeout: 1sec.  */
78   ts.tv_sec += 1;
79 
80   /* This call should never return.  */
81   if (pthread_cond_timedwait (&c, &m, &ts) != ETIMEDOUT)
82     {
83       puts ("cond_timedwait didn't time out");
84       exit (1);
85     }
86 
87   return NULL;
88 }
89 
90 
91 int
do_test(void)92 do_test (void)
93 {
94   pthread_t th;
95 
96   struct sigaction sa;
97   sigemptyset (&sa.sa_mask);
98   sa.sa_flags = 0;
99   sa.sa_handler = handler;
100   if (sigaction (SIGUSR1, &sa, NULL) != 0)
101     {
102       puts ("sigaction failed");
103       exit (1);
104     }
105 
106   if (pthread_barrier_init (&b, NULL, 2) != 0)
107     {
108       puts ("barrier_init failed");
109       exit (1);
110     }
111 
112   if (pthread_create (&th, NULL, tf, NULL) != 0)
113     {
114       puts ("create failed");
115       exit (1);
116     }
117 
118   int e = pthread_barrier_wait (&b);
119   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
120     {
121       puts ("barrier_wait failed");
122       exit (1);
123     }
124 
125   if (pthread_mutex_lock (&m) != 0)
126     {
127       puts ("mutex_lock failed");
128       exit (1);
129     }
130 
131   /* Send the thread a signal which it has blocked.  */
132   if (pthread_kill (th, SIGUSR1) != 0)
133     {
134       puts ("kill failed");
135       exit (1);
136     }
137 
138   if (pthread_mutex_unlock (&m) != 0)
139     {
140       puts ("mutex_unlock failed");
141       exit (1);
142     }
143 
144   void *r;
145   if (pthread_join (th, &r) != 0)
146     {
147       puts ("join failed");
148       exit (1);
149     }
150   if (r != NULL)
151     {
152       puts ("return value wrong");
153       exit (1);
154     }
155 
156   return 0;
157 }
158