1 | ////////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Ion Gaztanaga 2004-2012. Distributed under the Boost |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
6 | // |
7 | // See http://www.boost.org/libs/interprocess for documentation. |
8 | // |
9 | ////////////////////////////////////////////////////////////////////////////// |
10 | |
11 | #include <boost/interprocess/detail/workaround.hpp> |
12 | |
13 | //Robust mutex handling is only supported in conforming POSIX systems |
14 | #if !defined(BOOST_INTERPROCESS_POSIX_PROCESS_SHARED) || !defined(BOOST_INTERPROCESS_POSIX_ROBUST_MUTEXES) |
15 | |
16 | int main() |
17 | { |
18 | return 0; |
19 | } |
20 | |
21 | #else |
22 | |
23 | #include <boost/interprocess/detail/os_thread_functions.hpp> |
24 | |
25 | #include <boost/interprocess/sync/interprocess_mutex.hpp> |
26 | #include <boost/interprocess/sync/interprocess_recursive_mutex.hpp> |
27 | #include "mutex_test_template.hpp" |
28 | #include <iostream> |
29 | |
30 | |
31 | namespace boost { |
32 | namespace interprocess { |
33 | namespace test { |
34 | |
35 | template<typename M> |
36 | void lock_and_exit(void *, M &sm) |
37 | { |
38 | sm.lock(); |
39 | } |
40 | |
41 | enum EOwnerDeadLockType |
42 | { |
43 | OwnerDeadLock, |
44 | OwnerDeadTryLock, |
45 | OwnerDeadTimedLock |
46 | }; |
47 | |
48 | template<class M> |
49 | void test_owner_dead_mutex_do_lock(M &mtx, EOwnerDeadLockType lock_type) |
50 | { |
51 | switch (lock_type) |
52 | { |
53 | case OwnerDeadLock: |
54 | mtx.lock(); |
55 | break; |
56 | |
57 | case OwnerDeadTryLock: |
58 | mtx.try_lock(); |
59 | break; |
60 | |
61 | case OwnerDeadTimedLock: |
62 | mtx.timed_lock(boost_systemclock_delay_ms(msecs: 10)); |
63 | break; |
64 | } |
65 | } |
66 | |
67 | template<class M> |
68 | int test_owner_dead_mutex_impl(EOwnerDeadLockType lock_type) |
69 | { |
70 | using namespace boost::interprocess; |
71 | M mtx; |
72 | |
73 | // Locker thread launches and exits without releasing the mutex |
74 | ipcdetail::OS_thread_t tm1; |
75 | ipcdetail::thread_launch(tm1, thread_adapter<M>(&lock_and_exit, 0, mtx)); |
76 | ipcdetail::thread_join(thread: tm1); |
77 | BOOST_TRY { |
78 | test_owner_dead_mutex_do_lock(mtx, lock_type); |
79 | } |
80 | BOOST_CATCH(lock_exception& e) { |
81 | #ifndef BOOST_NO_EXCEPTIONS |
82 | if (e.get_error_code() == not_recoverable){ |
83 | //Now try once again to lock it, to make sure it's not recoverable |
84 | BOOST_TRY { |
85 | test_owner_dead_mutex_do_lock(mtx, lock_type); |
86 | } |
87 | BOOST_CATCH(lock_exception& e) { |
88 | if (e.get_error_code() == not_recoverable) |
89 | return 0; |
90 | else{ |
91 | std::cerr << "e.get_error_code() != not_recoverable! (2)" ; |
92 | return 3; |
93 | } |
94 | } |
95 | BOOST_CATCH(...) { |
96 | std::cerr << "lock_exception not thrown! (2)" ; |
97 | return 4; |
98 | } BOOST_CATCH_END |
99 | std::cerr << "Exception not thrown (2)!" ; |
100 | return 5; |
101 | } |
102 | else{ |
103 | std::cerr << "e.get_error_code() != not_recoverable!" ; |
104 | return 1; |
105 | } |
106 | #endif //BOOST_NO_EXCEPTIONS |
107 | } |
108 | BOOST_CATCH(...) { |
109 | std::cerr << "lock_exception not thrown!" ; |
110 | return 2; |
111 | } BOOST_CATCH_END |
112 | std::cerr << "Exception not thrown!" ; |
113 | return 3; |
114 | } |
115 | |
116 | template<class M> |
117 | int test_owner_dead_mutex() |
118 | { |
119 | int ret; |
120 | ret = test_owner_dead_mutex_impl<M>(OwnerDeadLock); |
121 | if (ret) return ret; |
122 | ret = test_owner_dead_mutex_impl<M>(OwnerDeadTryLock); |
123 | if (ret) return ret; |
124 | ret = test_owner_dead_mutex_impl<M>(OwnerDeadTimedLock); |
125 | return ret; |
126 | } |
127 | |
128 | }}} //boost::interprocess::test |
129 | |
130 | |
131 | int main () |
132 | { |
133 | using namespace boost::interprocess; |
134 | int ret; |
135 | std::cerr << "Testing interprocess_mutex" ; |
136 | ret = test::test_owner_dead_mutex<interprocess_mutex>(); |
137 | if (ret) |
138 | return ret; |
139 | |
140 | #ifdef BOOST_INTERPROCESS_POSIX_RECURSIVE_MUTEXES |
141 | std::cerr << "Testing interprocess_recursive_mutex" ; |
142 | ret = test::test_owner_dead_mutex<interprocess_recursive_mutex>(); |
143 | if (ret) |
144 | return ret; |
145 | #endif |
146 | |
147 | return ret; |
148 | } |
149 | |
150 | #endif |
151 | |
152 | |