chiark / gitweb /
Apply https://sourceware.org/git/?p=glibc.git;a=commit;h=d5dd6189d506068ed11c8bfa1e1e...
[eglibc.git] / linuxthreads / tst-sighandler1.c
1 /* Copyright (C) 2006 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, write to the Free
16    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17    02111-1307 USA.  */
18
19 #include <pthread.h>
20 #include <errno.h>
21 #include <stdio.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/wait.h>
26 #include <sys/time.h>
27 #include <limits.h>
28
29 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
30 pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
31 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
32
33 static void *
34 tf (void *arg)
35 {
36   int fd = (long) arg;
37   int pid = getpid ();
38 #ifdef TIMED
39   struct timespec ts;
40 #endif
41
42   if (pthread_mutex_lock (&mutex) != 0)
43     {
44       puts ("Could not lock mutex in thread");
45       return (void *) 1L;
46     }
47
48   write (fd, &pid, sizeof (int));
49
50   if (pthread_mutex_unlock (&mutex2) != 0)
51     {
52       puts ("Could not unlock mutex2 in thread");
53       return (void *) 1L;
54     }
55
56 #ifdef TIMED
57   ts.tv_sec = INT_MAX;
58   ts.tv_nsec = 0;
59   if (pthread_cond_timedwait (&cond, &mutex, &ts) != 0)
60     {
61       puts ("pthread_cond_wait failed in thread");
62       return (void *) 1L;
63     }
64 #else
65   if (pthread_cond_wait (&cond, &mutex) != 0)
66     {
67       puts ("pthread_cond_wait failed in thread");
68       return (void *) 1L;
69     }
70 #endif
71
72   if (pthread_mutex_unlock (&mutex) != 0)
73     {
74       puts ("Could not unlock mutex in thread");
75       return (void *) 1L;
76     }
77
78   return NULL;
79 }
80
81 static void
82 sig_segv (int unused)
83 {
84   exit (2);
85 }
86
87 int
88 do_test (void)
89 {
90   int fds[2];
91   pthread_t thr;
92
93   if (pipe (fds) < 0)
94     {
95       printf ("couldn't create pipe: %m\n");
96       return 1;
97     }
98
99   pid_t pid = fork ();
100   if (pid < 0)
101     {
102       printf ("fork failed: %m\n");
103       return 1;
104     }
105
106   if (!pid)
107     {
108       void *ret;
109
110       close (fds[0]);
111       signal (SIGSEGV, sig_segv);
112       pthread_mutex_lock (&mutex2);
113       pthread_create (&thr, NULL, tf, (void *) (long) (fds[1]));
114       /* Wait for the thread to go into cond_wait.  */
115       pthread_mutex_lock (&mutex2);
116       pthread_mutex_lock (&mutex);
117       write (fds[1], "", 1);
118       pthread_join (thr, &ret);
119       exit (0);
120     }
121
122   close (fds[1]);
123
124   int child_pid;
125   if (TEMP_FAILURE_RETRY (read (fds[0], &child_pid, sizeof (int)))
126       != sizeof (int))
127     {
128       puts ("could not read pid from child");
129       return 1;
130     }
131
132   char dummy;
133   if (TEMP_FAILURE_RETRY (read (fds[0], &dummy, 1)) != 1)
134     {
135       puts ("could not read sync byte from child");
136       return 1;
137     }
138
139   close (fds[0]);
140
141   /* The sync byte may come immediately after the mutex is released;
142      wait a little bit more to make sure the thread has suspended, to
143      test the right bug.  */
144   struct timespec ts;
145   ts.tv_sec = 0;
146   ts.tv_nsec = 200000000;
147   nanosleep (&ts, NULL);
148
149   kill (child_pid, SIGSEGV);
150
151   pid_t termpid;
152   int status;
153   termpid = TEMP_FAILURE_RETRY (waitpid (pid, &status, 0));
154   if (termpid == -1)
155     {
156       printf ("waitpid failed: %m\n");
157       return 1;
158     }
159   else if (termpid != pid)
160     {
161       printf ("waitpid returned %ld != %ld\n",
162               (long int) termpid, (long int) pid);
163       return 1;
164     }
165   else if (!WIFEXITED (status) || WEXITSTATUS (status) != 2)
166     {
167       puts ("child hasn't exited with exit status 2");
168       return 1;
169     }
170
171   return 0;
172 }
173
174 #define TEST_FUNCTION do_test ()
175 #include "../test-skeleton.c"