tst-malloc-fork-deadlock.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /* Test concurrent fork, getline, and fflush (NULL).
  2. Copyright (C) 2016-2019 Free Software Foundation, Inc.
  3. This file is part of the GNU C Library.
  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 License as
  6. published by the Free Software Foundation; either version 2.1 of the
  7. License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; see the file COPYING.LIB. If
  14. not, see <http://www.gnu.org/licenses/>. */
  15. #include <sys/wait.h>
  16. #include <unistd.h>
  17. #include <errno.h>
  18. #include <stdio.h>
  19. #include <pthread.h>
  20. #include <stdbool.h>
  21. #include <stdlib.h>
  22. #include <malloc.h>
  23. #include <time.h>
  24. #include <string.h>
  25. #include <signal.h>
  26. #include <support/xthread.h>
  27. #include <support/temp_file.h>
  28. #include <support/test-driver.h>
  29. enum {
  30. /* Number of threads which call fork. */
  31. fork_thread_count = 4,
  32. /* Number of threads which call getline (and, indirectly,
  33. malloc). */
  34. read_thread_count = 8,
  35. };
  36. static bool termination_requested;
  37. static void *
  38. fork_thread_function (void *closure)
  39. {
  40. while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
  41. {
  42. pid_t pid = fork ();
  43. if (pid < 0)
  44. {
  45. printf ("error: fork: %m\n");
  46. abort ();
  47. }
  48. else if (pid == 0)
  49. _exit (17);
  50. int status;
  51. if (waitpid (pid, &status, 0) < 0)
  52. {
  53. printf ("error: waitpid: %m\n");
  54. abort ();
  55. }
  56. if (!WIFEXITED (status) || WEXITSTATUS (status) != 17)
  57. {
  58. printf ("error: waitpid returned invalid status: %d\n", status);
  59. abort ();
  60. }
  61. }
  62. return NULL;
  63. }
  64. static char *file_to_read;
  65. static void *
  66. read_thread_function (void *closure)
  67. {
  68. FILE *f = fopen (file_to_read, "r");
  69. if (f == NULL)
  70. {
  71. printf ("error: fopen (%s): %m\n", file_to_read);
  72. abort ();
  73. }
  74. while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
  75. {
  76. rewind (f);
  77. char *line = NULL;
  78. size_t line_allocated = 0;
  79. ssize_t ret = getline (&line, &line_allocated, f);
  80. if (ret < 0)
  81. {
  82. printf ("error: getline: %m\n");
  83. abort ();
  84. }
  85. free (line);
  86. }
  87. fclose (f);
  88. return NULL;
  89. }
  90. static void *
  91. flushall_thread_function (void *closure)
  92. {
  93. while (!__atomic_load_n (&termination_requested, __ATOMIC_RELAXED))
  94. if (fflush (NULL) != 0)
  95. {
  96. printf ("error: fflush (NULL): %m\n");
  97. abort ();
  98. }
  99. return NULL;
  100. }
  101. static void
  102. create_threads (pthread_t *threads, size_t count, void *(*func) (void *))
  103. {
  104. for (size_t i = 0; i < count; ++i)
  105. threads[i] = xpthread_create (NULL, func, NULL);
  106. }
  107. static void
  108. join_threads (pthread_t *threads, size_t count)
  109. {
  110. for (size_t i = 0; i < count; ++i)
  111. xpthread_join (threads[i]);
  112. }
  113. /* Create a file which consists of a single long line, and assigns
  114. file_to_read. The hope is that this triggers an allocation in
  115. getline which needs a lock. */
  116. static void
  117. create_file_with_large_line (void)
  118. {
  119. int fd = create_temp_file ("bug19431-large-line", &file_to_read);
  120. if (fd < 0)
  121. {
  122. printf ("error: create_temp_file: %m\n");
  123. abort ();
  124. }
  125. FILE *f = fdopen (fd, "w+");
  126. if (f == NULL)
  127. {
  128. printf ("error: fdopen: %m\n");
  129. abort ();
  130. }
  131. for (int i = 0; i < 50000; ++i)
  132. fputc ('x', f);
  133. fputc ('\n', f);
  134. if (ferror (f))
  135. {
  136. printf ("error: fputc: %m\n");
  137. abort ();
  138. }
  139. if (fclose (f) != 0)
  140. {
  141. printf ("error: fclose: %m\n");
  142. abort ();
  143. }
  144. }
  145. static int
  146. do_test (void)
  147. {
  148. /* Make sure that we do not exceed the arena limit with the number
  149. of threads we configured. */
  150. if (mallopt (M_ARENA_MAX, 400) == 0)
  151. {
  152. printf ("error: mallopt (M_ARENA_MAX) failed\n");
  153. return 1;
  154. }
  155. /* Leave some room for shutting down all threads gracefully. */
  156. int timeout = 3;
  157. if (timeout > DEFAULT_TIMEOUT)
  158. timeout = DEFAULT_TIMEOUT - 1;
  159. create_file_with_large_line ();
  160. pthread_t fork_threads[fork_thread_count];
  161. create_threads (fork_threads, fork_thread_count, fork_thread_function);
  162. pthread_t read_threads[read_thread_count];
  163. create_threads (read_threads, read_thread_count, read_thread_function);
  164. pthread_t flushall_threads[1];
  165. create_threads (flushall_threads, 1, flushall_thread_function);
  166. struct timespec ts = {timeout, 0};
  167. if (nanosleep (&ts, NULL))
  168. {
  169. printf ("error: error: nanosleep: %m\n");
  170. abort ();
  171. }
  172. __atomic_store_n (&termination_requested, true, __ATOMIC_RELAXED);
  173. join_threads (flushall_threads, 1);
  174. join_threads (read_threads, read_thread_count);
  175. join_threads (fork_threads, fork_thread_count);
  176. free (file_to_read);
  177. return 0;
  178. }
  179. #include <support/test-driver.c>