Skip to content
This repository was archived by the owner on Jul 8, 2022. It is now read-only.

Commit 87e5bee

Browse files
authored
Merge pull request #665 from mliszcz/backport-fix-511-crash-race-condition-event-push
[Backport] Fix race conditions between polling threads and user threads pushing events
2 parents 526c2d1 + 5f89566 commit 87e5bee

File tree

3 files changed

+111
-89
lines changed

3 files changed

+111
-89
lines changed

cppapi/server/attribute.cpp

Lines changed: 110 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,9 +3774,13 @@ void Attribute::fire_change_event(DevFailed *except)
37743774
time_t change3_subscription,change4_subscription,change5_subscription;
37753775

37763776
now = time(NULL);
3777-
change3_subscription = now - event_change3_subscription;
3778-
change4_subscription = now - event_change4_subscription;
3779-
change5_subscription = now - event_change5_subscription;
3777+
3778+
{
3779+
omni_mutex_lock oml(EventSupplier::get_event_mutex());
3780+
change3_subscription = now - event_change3_subscription;
3781+
change4_subscription = now - event_change4_subscription;
3782+
change5_subscription = now - event_change5_subscription;
3783+
}
37803784

37813785
//
37823786
// Get the event supplier(s)
@@ -4017,54 +4021,58 @@ void Attribute::fire_change_event(DevFailed *except)
40174021
bool force_change = false;
40184022
bool quality_change = false;
40194023

4020-
if ((except != NULL) ||
4021-
(quality == Tango::ATTR_INVALID) ||
4022-
((except == NULL) && (prev_change_event.err == true)) ||
4023-
((quality != Tango::ATTR_INVALID) &&
4024-
(prev_change_event.quality == Tango::ATTR_INVALID)))
4025-
{
4026-
force_change = true;
4027-
}
4028-
40294024
vector<string> filterable_names;
40304025
vector<double> filterable_data;
40314026
vector<string> filterable_names_lg;
40324027
vector<long> filterable_data_lg;
40334028

4034-
if (except != NULL)
40354029
{
4036-
prev_change_event.err = true;
4037-
prev_change_event.except = *except;
4038-
}
4039-
else
4040-
{
4041-
Tango::AttrQuality the_quality;
4030+
omni_mutex_lock oml(EventSupplier::get_event_mutex());
40424031

4043-
if (send_attr_5 != NULL)
4032+
if ((except != NULL) ||
4033+
(quality == Tango::ATTR_INVALID) ||
4034+
((except == NULL) && (prev_change_event.err == true)) ||
4035+
((quality != Tango::ATTR_INVALID) &&
4036+
(prev_change_event.quality == Tango::ATTR_INVALID)))
40444037
{
4045-
the_quality = send_attr_5->quality;
4046-
prev_change_event.value_4 = send_attr_5->value;
4038+
force_change = true;
40474039
}
4048-
else if (send_attr_4 != NULL)
4040+
4041+
if (except != NULL)
40494042
{
4050-
the_quality = send_attr_4->quality;
4051-
prev_change_event.value_4 = send_attr_4->value;
4043+
prev_change_event.err = true;
4044+
prev_change_event.except = *except;
40524045
}
40534046
else
40544047
{
4055-
the_quality = send_attr->quality;
4056-
prev_change_event.value = send_attr->value;
4057-
}
4048+
Tango::AttrQuality the_quality;
40584049

4059-
if (prev_change_event.quality != the_quality)
4060-
{
4061-
quality_change = true;
4062-
}
4050+
if (send_attr_5 != NULL)
4051+
{
4052+
the_quality = send_attr_5->quality;
4053+
prev_change_event.value_4 = send_attr_5->value;
4054+
}
4055+
else if (send_attr_4 != NULL)
4056+
{
4057+
the_quality = send_attr_4->quality;
4058+
prev_change_event.value_4 = send_attr_4->value;
4059+
}
4060+
else
4061+
{
4062+
the_quality = send_attr->quality;
4063+
prev_change_event.value = send_attr->value;
4064+
}
40634065

4064-
prev_change_event.quality = the_quality;
4065-
prev_change_event.err = false;
4066+
if (prev_change_event.quality != the_quality)
4067+
{
4068+
quality_change = true;
4069+
}
4070+
4071+
prev_change_event.quality = the_quality;
4072+
prev_change_event.err = false;
4073+
}
4074+
prev_change_event.inited = true;
40664075
}
4067-
prev_change_event.inited = true;
40684076

40694077
filterable_names.push_back("forced_event");
40704078
if (force_change == true)
@@ -4199,9 +4207,12 @@ void Attribute::fire_archive_event(DevFailed *except)
41994207

42004208
now = time(NULL);
42014209

4202-
archive3_subscription = now - event_archive3_subscription;
4203-
archive4_subscription = now - event_archive4_subscription;
4204-
archive5_subscription = now - event_archive5_subscription;
4210+
{
4211+
omni_mutex_lock oml(EventSupplier::get_event_mutex());
4212+
archive3_subscription = now - event_archive3_subscription;
4213+
archive4_subscription = now - event_archive4_subscription;
4214+
archive5_subscription = now - event_archive5_subscription;
4215+
}
42054216

42064217
//
42074218
// Get the event supplier(s)
@@ -4458,60 +4469,73 @@ void Attribute::fire_archive_event(DevFailed *except)
44584469
{
44594470

44604471
//
4461-
// Execute detect_change only to calculate the delta_change_rel and
4462-
// delta_change_abs and force_change !
44634472
//
44644473

44654474
bool force_change = false;
44664475
bool quality_change = false;
44674476
double delta_change_rel = 0.0;
44684477
double delta_change_abs = 0.0;
44694478

4470-
if (event_supplier_nd != NULL)
4471-
event_supplier_nd->detect_change(*this, ad,true,delta_change_rel,delta_change_abs,except,force_change,dev);
4472-
else if (event_supplier_zmq != NULL)
4473-
event_supplier_zmq->detect_change(*this, ad,true,delta_change_rel,delta_change_abs,except,force_change,dev);
4474-
4475-
4476-
vector<string> filterable_names;
4477-
vector<double> filterable_data;
4478-
vector<string> filterable_names_lg;
4479-
vector<long> filterable_data_lg;
4480-
4481-
if (except != NULL)
4482-
{
4483-
prev_archive_event.err = true;
4484-
prev_archive_event.except = *except;
4485-
}
4486-
else
44874479
{
4488-
Tango::AttrQuality the_quality;
4480+
omni_mutex_lock oml(EventSupplier::get_event_mutex());
44894481

4490-
if (send_attr_5 != Tango_nullptr)
4482+
// Execute detect_change only to calculate the delta_change_rel and
4483+
// delta_change_abs and force_change !
4484+
4485+
if (event_supplier_nd || event_supplier_zmq)
44914486
{
4492-
prev_archive_event.value_4 = send_attr_5->value;
4493-
the_quality = send_attr_5->quality;
4487+
EventSupplier* event_supplier = event_supplier_nd ? event_supplier_nd : event_supplier_zmq;
4488+
event_supplier->detect_change(
4489+
*this,
4490+
ad,
4491+
true,
4492+
delta_change_rel,
4493+
delta_change_abs,
4494+
except,
4495+
force_change,
4496+
dev);
44944497
}
4495-
else if (send_attr_4 != Tango_nullptr)
4498+
4499+
if (except != NULL)
44964500
{
4497-
prev_archive_event.value_4 = send_attr_4->value;
4498-
the_quality = send_attr_4->quality;
4501+
prev_archive_event.err = true;
4502+
prev_archive_event.except = *except;
44994503
}
45004504
else
45014505
{
4502-
prev_archive_event.value = send_attr->value;
4503-
the_quality = send_attr->quality;
4504-
}
4506+
Tango::AttrQuality the_quality;
45054507

4506-
if (prev_archive_event.quality != the_quality)
4507-
{
4508-
quality_change = true;
4509-
}
4508+
if (send_attr_5 != Tango_nullptr)
4509+
{
4510+
prev_archive_event.value_4 = send_attr_5->value;
4511+
the_quality = send_attr_5->quality;
4512+
}
4513+
else if (send_attr_4 != Tango_nullptr)
4514+
{
4515+
prev_archive_event.value_4 = send_attr_4->value;
4516+
the_quality = send_attr_4->quality;
4517+
}
4518+
else
4519+
{
4520+
prev_archive_event.value = send_attr->value;
4521+
the_quality = send_attr->quality;
4522+
}
4523+
4524+
if (prev_archive_event.quality != the_quality)
4525+
{
4526+
quality_change = true;
4527+
}
45104528

4511-
prev_archive_event.quality = the_quality;
4512-
prev_archive_event.err = false;
4529+
prev_archive_event.quality = the_quality;
4530+
prev_archive_event.err = false;
4531+
}
4532+
prev_archive_event.inited = true;
45134533
}
4514-
prev_archive_event.inited = true;
4534+
4535+
vector<string> filterable_names;
4536+
vector<double> filterable_data;
4537+
vector<string> filterable_names_lg;
4538+
vector<long> filterable_data_lg;
45154539

45164540
filterable_names.push_back("forced_event");
45174541
if (force_change == true)
@@ -4642,9 +4666,12 @@ void Attribute::fire_event(vector<string> &filt_names,vector<double> &filt_vals,
46424666

46434667
now = time(NULL);
46444668

4645-
user3_subscription = now - event_user3_subscription;
4646-
user4_subscription = now - event_user4_subscription;
4647-
user5_subscription = now - event_user5_subscription;
4669+
{
4670+
omni_mutex_lock oml(EventSupplier::get_event_mutex());
4671+
user3_subscription = now - event_user3_subscription;
4672+
user4_subscription = now - event_user4_subscription;
4673+
user5_subscription = now - event_user5_subscription;
4674+
}
46484675

46494676
//
46504677
// Get the event supplier(s)
@@ -4914,9 +4941,12 @@ void Attribute::fire_error_periodic_event(DevFailed *except)
49144941

49154942
now = time(NULL);
49164943

4917-
periodic3_subscription = now - event_periodic3_subscription;
4918-
periodic4_subscription = now - event_periodic4_subscription;
4919-
periodic5_subscription = now - event_periodic5_subscription;
4944+
{
4945+
omni_mutex_lock oml(EventSupplier::get_event_mutex());
4946+
periodic3_subscription = now - event_periodic3_subscription;
4947+
periodic4_subscription = now - event_periodic4_subscription;
4948+
periodic5_subscription = now - event_periodic5_subscription;
4949+
}
49204950

49214951
vector<int> client_libs = get_client_lib(PERIODIC_EVENT); // We want a copy
49224952

cppapi/server/eventsupplier.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,12 +1182,6 @@ bool EventSupplier::detect_change(Attribute &attr, struct SuppliedEventData &att
11821182
the_new_any = &(attr_value.attr_val->value);
11831183
}
11841184

1185-
//
1186-
// get the mutex to synchronize the sending of events
1187-
//
1188-
1189-
omni_mutex_lock l(detect_mutex);
1190-
11911185
//
11921186
// Send event, if the read_attribute failed or if it is the first time that the read_attribute succeed after a failure.
11931187
// Same thing if the attribute quality factor changes to INVALID

cppapi/server/eventsupplier.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,7 @@ protected :
174174
static omni_mutex push_mutex;
175175
static omni_condition push_cond;
176176

177-
// Added a mutex to synchronize the access to
178-
// detect_event which is used
179-
// from different threads
177+
// Unused, replaced with event_mutex. Left for backward compatibility.
180178
static omni_mutex detect_mutex;
181179

182180
private:

0 commit comments

Comments
 (0)