Avoid array-bounds warning for strncat on i586 (bug 20260)
[glibc.git] / malloc / tst-malloc-fork-deadlock.c
blob94549ca459164103834d46d8358e56d3b747143d
1 /* Test concurrent fork, getline, and fflush (NULL).
2 Copyright (C) 2016 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public License as
7 published by the Free Software Foundation; either version 2.1 of the
8 License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, see <http://www.gnu.org/licenses/>. */
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <pthread.h>
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include <malloc.h>
27 #include <time.h>
28 #include <string.h>
29 #include <signal.h>
31 static int do_test (void);
32 #define TEST_FUNCTION do_test ()
33 #include "../test-skeleton.c"
35 enum {
36 /* Number of threads which call fork. */
37 fork_thread_count = 4,
38 /* Number of threads which call getline (and, indirectly,
39 malloc). */
40 read_thread_count = 8,
43 static bool termination_requested;
45 static void *
46 fork_thread_function (void *closure)
48 while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
50 pid_t pid = fork ();
51 if (pid < 0)
53 printf ("error: fork: %m\n");
54 abort ();
56 else if (pid == 0)
57 _exit (17);
59 int status;
60 if (waitpid (pid, &status, 0) < 0)
62 printf ("error: waitpid: %m\n");
63 abort ();
65 if (!WIFEXITED (status) || WEXITSTATUS (status) != 17)
67 printf ("error: waitpid returned invalid status: %d\n", status);
68 abort ();
71 return NULL;
74 static char *file_to_read;
76 static void *
77 read_thread_function (void *closure)
79 FILE *f = fopen (file_to_read, "r");
80 if (f == NULL)
82 printf ("error: fopen (%s): %m\n", file_to_read);
83 abort ();
86 while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
88 rewind (f);
89 char *line = NULL;
90 size_t line_allocated = 0;
91 ssize_t ret = getline (&line, &line_allocated, f);
92 if (ret < 0)
94 printf ("error: getline: %m\n");
95 abort ();
97 free (line);
99 fclose (f);
101 return NULL;
104 static void *
105 flushall_thread_function (void *closure)
107 while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
108 if (fflush (NULL) != 0)
110 printf ("error: fflush (NULL): %m\n");
111 abort ();
113 return NULL;
116 static void
117 create_threads (pthread_t *threads, size_t count, void *(*func) (void *))
119 for (size_t i = 0; i < count; ++i)
121 int ret = pthread_create (threads + i, NULL, func, NULL);
122 if (ret != 0)
124 errno = ret;
125 printf ("error: pthread_create: %m\n");
126 abort ();
131 static void
132 join_threads (pthread_t *threads, size_t count)
134 for (size_t i = 0; i < count; ++i)
136 int ret = pthread_join (threads[i], NULL);
137 if (ret != 0)
139 errno = ret;
140 printf ("error: pthread_join: %m\n");
141 abort ();
146 /* Create a file which consists of a single long line, and assigns
147 file_to_read. The hope is that this triggers an allocation in
148 getline which needs a lock. */
149 static void
150 create_file_with_large_line (void)
152 int fd = create_temp_file ("bug19431-large-line", &file_to_read);
153 if (fd < 0)
155 printf ("error: create_temp_file: %m\n");
156 abort ();
158 FILE *f = fdopen (fd, "w+");
159 if (f == NULL)
161 printf ("error: fdopen: %m\n");
162 abort ();
164 for (int i = 0; i < 50000; ++i)
165 fputc ('x', f);
166 fputc ('\n', f);
167 if (ferror (f))
169 printf ("error: fputc: %m\n");
170 abort ();
172 if (fclose (f) != 0)
174 printf ("error: fclose: %m\n");
175 abort ();
179 static int
180 do_test (void)
182 /* Make sure that we do not exceed the arena limit with the number
183 of threads we configured. */
184 if (mallopt (M_ARENA_MAX, 400) == 0)
186 printf ("error: mallopt (M_ARENA_MAX) failed\n");
187 return 1;
190 /* Leave some room for shutting down all threads gracefully. */
191 int timeout = 3;
192 if (timeout > TIMEOUT)
193 timeout = TIMEOUT - 1;
195 create_file_with_large_line ();
197 pthread_t fork_threads[fork_thread_count];
198 create_threads (fork_threads, fork_thread_count, fork_thread_function);
199 pthread_t read_threads[read_thread_count];
200 create_threads (read_threads, read_thread_count, read_thread_function);
201 pthread_t flushall_threads[1];
202 create_threads (flushall_threads, 1, flushall_thread_function);
204 struct timespec ts = {timeout, 0};
205 if (nanosleep (&ts, NULL))
207 printf ("error: error: nanosleep: %m\n");
208 abort ();
211 __atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED);
213 join_threads (flushall_threads, 1);
214 join_threads (read_threads, read_thread_count);
215 join_threads (fork_threads, fork_thread_count);
217 free (file_to_read);
219 return 0;