1 /* Test the interaction of fork and robust mutexes.
2 Copyright (C) 2017-2018 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
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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; if not, see
17 <http://www.gnu.org/licenses/>. */
22 #include <support/check.h>
23 #include <support/test-driver.h>
24 #include <support/xthread.h>
25 #include <support/xunistd.h>
28 /* Data shared between processes. */
31 pthread_mutex_t parent_mutex
;
32 pthread_mutex_t child_mutex
;
35 /* These flags control which mutex settings are enabled in the parent
36 and child (separately). */
44 /* All bits combined. */
49 mutex_init (pthread_mutex_t
*mutex
, int bits
)
51 pthread_mutexattr_t attr
;
52 xpthread_mutexattr_init (&attr
);
53 if (bits
& mutex_pshared
)
54 xpthread_mutexattr_setpshared (&attr
, PTHREAD_PROCESS_SHARED
);
55 if (bits
& mutex_robust
)
56 xpthread_mutexattr_setrobust (&attr
, PTHREAD_MUTEX_ROBUST
);
58 xpthread_mutexattr_setprotocol (&attr
, PTHREAD_PRIO_INHERIT
);
59 if (bits
& mutex_check
)
60 xpthread_mutexattr_settype (&attr
, PTHREAD_MUTEX_ERRORCHECK
);
61 xpthread_mutex_init (mutex
, &attr
);
62 xpthread_mutexattr_destroy (&attr
);
66 one_test (int parent_bits
, int child_bits
, int nonshared_bits
,
67 bool lock_nonshared
, bool lock_child
)
70 struct shared
*shared
= xmmap (NULL
, sizeof (*shared
),
71 PROT_READ
| PROT_WRITE
,
72 MAP_ANONYMOUS
| MAP_SHARED
, -1);
73 mutex_init (&shared
->parent_mutex
, parent_bits
);
74 mutex_init (&shared
->child_mutex
, child_bits
);
76 /* Acquire the parent mutex in the parent. */
77 xpthread_mutex_lock (&shared
->parent_mutex
);
79 pthread_mutex_t nonshared_mutex
;
80 mutex_init (&nonshared_mutex
, nonshared_bits
);
82 xpthread_mutex_lock (&nonshared_mutex
);
89 xpthread_mutex_lock (&shared
->child_mutex
);
91 xmunmap (shared
, sizeof (*shared
));
93 /* Reinitialize the non-shared mutex if it was locked in the
95 mutex_init (&nonshared_mutex
, nonshared_bits
);
96 xpthread_mutex_lock (&nonshared_mutex
);
97 /* For robust mutexes, the _exit call will perform the unlock
99 if (lock_child
&& !(child_bits
& mutex_robust
))
100 xpthread_mutex_unlock (&shared
->child_mutex
);
103 /* Parent process. */
106 xwaitpid (pid
, &status
, 0);
107 TEST_VERIFY (status
== 0);
110 if (parent_bits
& mutex_check
)
111 /* Test for expected self-deadlock. This is only possible to
112 detect if the mutex is error-checking. */
113 TEST_VERIFY_EXIT (pthread_mutex_lock (&shared
->parent_mutex
) == EDEADLK
);
118 /* Child process. We can perform some checks only if we are
119 dealing with process-shared mutexes. */
120 if (parent_bits
& mutex_pshared
)
121 /* It must not be possible to acquire the parent mutex.
123 NB: This check touches a mutex which has been acquired in
124 the parent at fork time, so it might be deemed undefined
125 behavior, pending the resolution of Austin Groups issue
127 TEST_VERIFY_EXIT (pthread_mutex_trylock (&shared
->parent_mutex
)
129 if (lock_child
&& (child_bits
& mutex_robust
))
131 if (!(child_bits
& mutex_pshared
))
132 /* No further tests possible. */
134 TEST_VERIFY_EXIT (pthread_mutex_lock (&shared
->child_mutex
)
136 xpthread_mutex_consistent (&shared
->child_mutex
);
139 /* We did not acquire the lock in the first child process, or
140 we unlocked the mutex again because the mutex is not a
142 xpthread_mutex_lock (&shared
->child_mutex
);
143 xpthread_mutex_unlock (&shared
->child_mutex
);
146 /* Parent process. */
149 xwaitpid (pid
, &status
, 0);
150 TEST_VERIFY (status
== 0);
154 xpthread_mutex_unlock (&nonshared_mutex
);
155 xpthread_mutex_unlock (&shared
->parent_mutex
);
156 xpthread_mutex_destroy (&shared
->parent_mutex
);
157 xpthread_mutex_destroy (&shared
->child_mutex
);
158 xpthread_mutex_destroy (&nonshared_mutex
);
159 xmunmap (shared
, sizeof (*shared
));
165 for (int parent_bits
= 0; parent_bits
<= mutex_all_bits
; ++parent_bits
)
166 for (int child_bits
= 0; child_bits
<= mutex_all_bits
; ++child_bits
)
167 for (int nonshared_bits
= 0; nonshared_bits
<= mutex_all_bits
;
169 for (int lock_nonshared
= 0; lock_nonshared
< 2; ++lock_nonshared
)
170 for (int lock_child
= 0; lock_child
< 2; ++lock_child
)
173 printf ("info: parent_bits=0x%x child_bits=0x%x"
174 " nonshared_bits=0x%x%s%s\n",
175 parent_bits
, child_bits
, nonshared_bits
,
176 lock_nonshared
? " lock_nonshared" : "",
177 lock_child
? " lock_child" : "");
178 one_test (parent_bits
, child_bits
, nonshared_bits
,
179 lock_nonshared
, lock_child
);
185 #include <support/test-driver.c>