1 /* Test concurrent fork, getline, and fflush (NULL).
2 Copyright (C) 2016-2024 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 <https://www.gnu.org/licenses/>. */
31 #include <support/xthread.h>
32 #include <support/temp_file.h>
33 #include <support/test-driver.h>
36 /* Number of threads which call fork. */
37 fork_thread_count
= 4,
38 /* Number of threads which call getline (and, indirectly,
40 read_thread_count
= 8,
43 static bool termination_requested
;
46 fork_thread_function (void *closure
)
48 while (!__atomic_load_n (&termination_requested
, __ATOMIC_RELAXED
))
53 printf ("error: fork: %m\n");
60 if (waitpid (pid
, &status
, 0) < 0)
62 printf ("error: waitpid: %m\n");
65 if (!WIFEXITED (status
) || WEXITSTATUS (status
) != 17)
67 printf ("error: waitpid returned invalid status: %d\n", status
);
74 static char *file_to_read
;
77 read_thread_function (void *closure
)
79 FILE *f
= fopen (file_to_read
, "r");
82 printf ("error: fopen (%s): %m\n", file_to_read
);
86 while (!__atomic_load_n (&termination_requested
, __ATOMIC_RELAXED
))
90 size_t line_allocated
= 0;
91 ssize_t ret
= getline (&line
, &line_allocated
, f
);
94 printf ("error: getline: %m\n");
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");
117 create_threads (pthread_t
*threads
, size_t count
, void *(*func
) (void *))
119 for (size_t i
= 0; i
< count
; ++i
)
120 threads
[i
] = xpthread_create (NULL
, func
, NULL
);
124 join_threads (pthread_t
*threads
, size_t count
)
126 for (size_t i
= 0; i
< count
; ++i
)
127 xpthread_join (threads
[i
]);
130 /* Create a file which consists of a single long line, and assigns
131 file_to_read. The hope is that this triggers an allocation in
132 getline which needs a lock. */
134 create_file_with_large_line (void)
136 int fd
= create_temp_file ("bug19431-large-line", &file_to_read
);
139 printf ("error: create_temp_file: %m\n");
142 FILE *f
= fdopen (fd
, "w+");
145 printf ("error: fdopen: %m\n");
148 for (int i
= 0; i
< 50000; ++i
)
153 printf ("error: fputc: %m\n");
158 printf ("error: fclose: %m\n");
166 /* Make sure that we do not exceed the arena limit with the number
167 of threads we configured. */
168 if (mallopt (M_ARENA_MAX
, 400) == 0)
170 printf ("error: mallopt (M_ARENA_MAX) failed\n");
174 /* Leave some room for shutting down all threads gracefully. */
176 if (timeout
> DEFAULT_TIMEOUT
)
177 timeout
= DEFAULT_TIMEOUT
- 1;
179 create_file_with_large_line ();
181 pthread_t fork_threads
[fork_thread_count
];
182 create_threads (fork_threads
, fork_thread_count
, fork_thread_function
);
183 pthread_t read_threads
[read_thread_count
];
184 create_threads (read_threads
, read_thread_count
, read_thread_function
);
185 pthread_t flushall_threads
[1];
186 create_threads (flushall_threads
, 1, flushall_thread_function
);
188 struct timespec ts
= {timeout
, 0};
189 if (nanosleep (&ts
, NULL
))
191 printf ("error: error: nanosleep: %m\n");
195 __atomic_store_n (&termination_requested
, true, __ATOMIC_RELAXED
);
197 join_threads (flushall_threads
, 1);
198 join_threads (read_threads
, read_thread_count
);
199 join_threads (fork_threads
, fork_thread_count
);
206 #include <support/test-driver.c>