Unlocking a robust mutex in a cleanup handler
Konstantin Belousov
kostikbel at gmail.com
Tue Dec 6 14:48:17 UTC 2016
On Tue, Dec 06, 2016 at 03:17:41PM +0100, Dimitri Staessens wrote:
> Dear Konstantin,
>
> thanks for your immediate response. Please find attached a minimal code
> example. I do hope I'm sending in the correct format, I'm new to the
> community.
>
> The test creates an integer, robust mutex and condition variable in
> shared memory. A thread blocks on that condition variable with the
> associated mutex. After one second, the main thread cancels the blocking
> thread.
>
> I compile as follows:
>
> gcc robust_test.c -lpthread -lrt -o robust_test
>
> and run
>
> ./robust_test
>
> On linux it gives the following output:
> [dstaesse at phoneutria]$ ./robust_test
> Initializing...
> Starting thread...
> Sleeping for one second...
> Thread started...
> Cancelling thread...
> Thread finished.
> Bye.
>
> On FreeBSD I get the following:
> $ ./robust_test
> Initializing...
> Starting thread...
> Sleeping for one second...
> Thread started...
> Cancelling thread...
> Fatal error 'inact_mtx enter' at line 188 in file
> /usr/src/lib/libthr/thread/thr_mutex.c (errno = 0)
> Abort trap (core dumped)
Try this patch. It worked for me.
It is enough to patch and then rebuild only libthr:
cd /usr/src
patch -p1 <patch
(cd lib/libthr && make WITHOUT_TESTS=yes all install)
diff --git a/lib/libthr/thread/thr_cond.c b/lib/libthr/thread/thr_cond.c
index 506b8eca9e7..64d075ca06f 100644
--- a/lib/libthr/thread/thr_cond.c
+++ b/lib/libthr/thread/thr_cond.c
@@ -224,16 +224,26 @@ cond_wait_kernel(struct pthread_cond *cvp, struct pthread_mutex *mp,
* state and unlock the mutex without making the state
* consistent and the state will be unrecoverable.
*/
- if (error2 == 0 && cancel)
+ if (error2 == 0 && cancel) {
+ if (robust) {
+ _mutex_leave_robust(curthread, mp);
+ robust = false;
+ }
_thr_testcancel(curthread);
+ }
if (error == EINTR)
error = 0;
} else {
/* We know that it didn't unlock the mutex. */
_mutex_cv_attach(mp, recurse);
- if (cancel)
+ if (cancel) {
+ if (robust) {
+ _mutex_leave_robust(curthread, mp);
+ robust = false;
+ }
_thr_testcancel(curthread);
+ }
error2 = 0;
}
if (robust)
More information about the freebsd-threads
mailing list