Skip to content

Commit d584217

Browse files
joelpintoduartenfonseca
authored andcommitted
Add helgrind dubious locks suppresses
Summary Add helgrind dubious POSIX API misuse suppresses and update condition variable ordering. Details When using condition variables and notifying threads, the signaling thread can unlock the associated mutex before or after the signaling (or might not even acquire the mutex if no predicate state needs to be updated). Despite the fact that signaling with the associated mutex acquired might be considered a pessimization by some references, valgrind documentation states that helgrind will consider an error when a thread signals through pthread_cond_signal or pthread_cond_broadcast and the mutex associated with the signal is not locked at the time the it is sent as it is considered that it can cause subtle race conditions and unpredictable behavior. This commit updates the pessimization removal added in the network tests and suppresses all related POSIX API misuses from boost library. An alternative could be disabling the report-signal-unlocked helgrind flag.
1 parent c1fde4d commit d584217

File tree

5 files changed

+109
-13
lines changed

5 files changed

+109
-13
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ if (NOT MSVC)
145145
endif ()
146146

147147
if (VALGRIND_TYPE STREQUAL "helgrind")
148-
set(TEST_ENTRYPOINT ${TEST_ENTRYPOINT} --suppressions=${VALGRIND_SUPPRESS_FILE} --gen-suppressions=all --log-file=${VALGRIND_LOGS_DIR}/test_name.out)
148+
set(TEST_ENTRYPOINT ${TEST_ENTRYPOINT} --show-error-list=yes --suppressions=${VALGRIND_SUPPRESS_FILE} --gen-suppressions=all --log-file=${VALGRIND_LOGS_DIR}/test_name.out)
149149
endif ()
150150

151151
if (VALGRIND_TYPE STREQUAL "massif")

test/network_tests/offer_tests/offer_test_multiple_offerings.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@ class common {
3535
std::condition_variable condition_availability_;
3636
std::atomic_bool availability_;
3737
std::atomic_bool msg_sent_;
38+
std::mutex mutex_;
3839
};
3940

4041
void common::on_availability(service_t _service_id, instance_t _instance_id, bool _is_available) {
4142
if (_service_id == service_id_ && _instance_id == instance_id_) {
4243
if (_is_available) {
4344
// NOTE: Using the most strict memory ordering operation.
4445
// Refer to https://en.cppreference.com/w/cpp/atomic/memory_order for possible options
46+
std::lock_guard<std::mutex> lock(mutex_);
4547
availability_.store(true);
4648
condition_availability_.notify_one();
4749
} else {
@@ -160,7 +162,6 @@ class client : common {
160162
private:
161163
std::condition_variable condition_message_received_;
162164
std::condition_variable condition_message_sent_;
163-
std::mutex mutex_;
164165

165166
std::atomic_bool message_received_;
166167

@@ -228,9 +229,6 @@ class server : common {
228229
void on_availability(service_t _service_id, instance_t _instance_id, bool _is_available) {
229230
common::on_availability(_service_id, _instance_id, _is_available);
230231
}
231-
232-
private:
233-
std::mutex mutex_;
234232
};
235233

236234
class vsomeip_daemon {

test/network_tests/subscribe_notify_tests/subscribe_notify_test_service.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -129,8 +129,8 @@ class subscribe_notify_test_service : public vsomeip_utilities::base_logger {
129129
if (_state == vsomeip::state_type_e::ST_REGISTERED) {
130130
std::lock_guard<std::mutex> its_lock(mutex_);
131131
wait_until_registered_ = false;
132+
condition_.notify_one();
132133
}
133-
condition_.notify_one();
134134
}
135135

136136
void on_availability(vsomeip::service_t _service,
@@ -157,8 +157,8 @@ class subscribe_notify_test_service : public vsomeip_utilities::base_logger {
157157
return v.second;})) {
158158
std::lock_guard<std::mutex> its_lock(mutex_);
159159
wait_until_other_services_available_ = false;
160+
condition_.notify_one();
160161
}
161-
condition_.notify_one();
162162
}
163163
}
164164

@@ -206,9 +206,10 @@ class subscribe_notify_test_service : public vsomeip_utilities::base_logger {
206206
// notify the notify thread to start sending out notifications
207207
std::lock_guard<std::mutex> its_lock(notify_mutex_);
208208
wait_for_notify_ = false;
209+
notify_condition_.notify_one();
209210
notified = true;
210211
}
211-
notify_condition_.notify_one();
212+
212213
return true;
213214
}
214215

@@ -245,8 +246,8 @@ class subscribe_notify_test_service : public vsomeip_utilities::base_logger {
245246
if(all_notifications_received()) {
246247
std::lock_guard<std::mutex> its_lock(stop_mutex_);
247248
wait_for_stop_ = false;
249+
stop_condition_.notify_one();
248250
}
249-
stop_condition_.notify_one();
250251
}
251252
}
252253

@@ -396,8 +397,8 @@ class subscribe_notify_test_service : public vsomeip_utilities::base_logger {
396397
{
397398
std::lock_guard<std::mutex> its_lock(mutex_);
398399
wait_until_notified_from_other_services_ = false;
400+
condition_.notify_one();
399401
}
400-
condition_.notify_one();
401402

402403
stop_offer();
403404

test/network_tests/suspend_resume_tests/suspend_resume_test_service.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ class suspend_resume_test_service : public vsomeip_utilities::base_logger {
5757
void stop() {
5858

5959
is_running_ = false;
60-
sr_cv_.notify_one();
60+
{
61+
std::lock_guard<std::mutex> its_lock(sr_mutex_);
62+
sr_cv_.notify_one();
63+
}
6164

6265
app_->stop();
6366

@@ -143,10 +146,16 @@ class suspend_resume_test_service : public vsomeip_utilities::base_logger {
143146

144147
switch (its_control_byte) {
145148
case TEST_SUSPEND:
146-
sr_cv_.notify_one();
149+
{
150+
std::lock_guard<std::mutex> its_lock(sr_mutex_);
151+
sr_cv_.notify_one();
152+
}
147153
break;
148154
case TEST_STOP:
149-
cv_.notify_one();
155+
{
156+
std::lock_guard<std::mutex> its_lock(mutex_);
157+
cv_.notify_one();
158+
}
150159
break;
151160
default:;
152161
}

zuul/network-tests/valgrind/helgrind.supp

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,91 @@
2222
...
2323
obj:/usr/lib/libdlt.so.*
2424
}
25+
{
26+
# Dubious: lock is not held by any thread when closing socket.
27+
deregister_application
28+
Helgrind:Misc
29+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
30+
fun:_ZN5boost4asio6detail13epoll_reactor21deregister_descriptorEiRPNS2_16descriptor_stateEb
31+
...
32+
obj:/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
33+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
34+
fun:start_thread
35+
fun:clone
36+
}
37+
{
38+
# Dubious: lock is not held by any thread on strand handler dispatch.
39+
strand_dispatch
40+
Helgrind:Misc
41+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
42+
fun:_ZN5boost4asio6detail14strand_service11do_dispatchERPNS2_11strand_implEPNS1_19scheduler_operationE
43+
...
44+
obj:/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
45+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
46+
fun:start_thread
47+
fun:clone
48+
}
49+
{
50+
# Dubious: lock is not held by any thread when a job is posted to a strand.
51+
initiate_strand
52+
Helgrind:Misc
53+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
54+
...
55+
fun:initiate<boost::asio::io_context::strand::initiate_post, std::_Bind<*>, boost::asio::io_context::strand*>
56+
...
57+
obj:/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
58+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
59+
fun:start_thread
60+
fun:clone
61+
}
62+
{
63+
# Dubious: lock is not held by any thread when boost io scheduler tries to execute a thread.
64+
unlock_and_signal_one
65+
Helgrind:Misc
66+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
67+
fun:unlock_and_signal_one<boost::asio::detail::conditionally_enabled_mutex::scoped_lock>
68+
...
69+
fun:_ZN5boost4asio6detail9scheduler*
70+
...
71+
}
72+
{
73+
# Dubious: lock is not held by any thread when boost io scheduler tries to execute a thread.
74+
maybe_unlock_and_signal_one
75+
Helgrind:Misc
76+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
77+
fun:maybe_unlock_and_signal_one<boost::asio::detail::conditionally_enabled_mutex::scoped_lock>
78+
...
79+
fun:_ZN5boost4asio6detail9scheduler*
80+
...
81+
}
82+
{
83+
# Dubious: lock is not held by any thread when canceling steady timer
84+
cancel_steady_timer
85+
Helgrind:Misc
86+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
87+
fun:cancel_timer<boost::asio::detail::chrono_time_traits<std::chrono::_V2::steady_clock, boost::asio::wait_traits<std::chrono::_V2::steady_clock> > >
88+
fun:cancel
89+
...
90+
}
91+
{
92+
# Dubious: lock is not held by any thread when canceling steady timer
93+
cancel_steady_timer_diff_func_sign
94+
Helgrind:Misc
95+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
96+
fun:_ZN5boost4asio6detail13epoll_reactor12cancel_timerINS1_18chrono_time_traitsINSt6chrono3_V212steady_clockENS0_11wait_traitsIS7_EEEEEEmRNS1_11timer_queueIT_EERNSD_14per_timer_data*
97+
...
98+
obj:/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
99+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
100+
fun:start_thread
101+
fun:clone
102+
}
103+
{
104+
# Dubious: lock is not held by any thread upon beginning of socket asynchronous operation.
105+
async_operation_start
106+
Helgrind:Misc
107+
obj:/usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so
108+
fun:start_op
109+
fun:start_op
110+
...
111+
obj:/usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.30
112+
}

0 commit comments

Comments
 (0)