Skip to content

Commit cfeaa26

Browse files
nacarvalhodahlerlend
authored andcommitted
BUG#35998554: get_group_member_info_*() does not distinguish member not found from error
It was discovered that some methods from `Group_member_info_manager` class did return the same value for distinct situations, which could be masquerading errors. One case is ``` Group_member_info * Group_member_info_manager::get_group_member_info_by_member_id( const Gcs_member_identifier &id); ``` that does return a allocated copy of the `member_info` when the member exists on the `Group_member_info_manager`, or returns `nullprt` when the member does not exist. Though `nullptr` can also be returned when the memory allocation of the copy fails, which means that the method caller is unable to distinguish: * member not found; * no memory available to construct the object. On both situations the method caller will interpret `nullptr` as member not found which can leverage incorrect decisions. The same pattern exists on the methods: * Group_member_info_manager::get_group_member_info() * Group_member_info_manager::get_group_member_info_by_index() * Group_member_info_manager::get_group_member_info_by_member_id() * Group_member_info_manager::get_primary_member_info() To solve the above issue, the four methods were refactored to: 1) return a boolean value to state if the member was found; 2) receive a out parameter that is a local reference to the method caller that is updated when the member is found. The use of the reference eliminates the allocation of the memory. Change-Id: Ic10263943fc63f40cdda506a59f10962aa208d92
1 parent a32b194 commit cfeaa26

17 files changed

+413
-307
lines changed

plugin/group_replication/include/member_info.h

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
#include "my_inttypes.h"
4444
#include "my_sys.h"
45+
#include "mysql/binlog/event/nodiscard.h"
4546
#include "plugin/group_replication/include/gcs_plugin_messages.h"
4647
#include "plugin/group_replication/include/member_version.h"
4748
#include "plugin/group_replication/include/plugin_psi.h"
@@ -253,6 +254,14 @@ class Group_member_info : public Plugin_gcs_message {
253254
*/
254255
void operator delete(void *ptr) noexcept { my_free(ptr); }
255256

257+
/**
258+
Group_member_info empty constructor
259+
260+
@param[in] psi_mutex_key_arg mutex key
261+
*/
262+
Group_member_info(PSI_mutex_key psi_mutex_key_arg =
263+
key_GR_LOCK_group_member_info_update_lock);
264+
256265
/**
257266
Group_member_info constructor
258267
@@ -274,13 +283,13 @@ class Group_member_info : public Plugin_gcs_message {
274283
check
275284
@param[in] member_weight_arg member_weight
276285
@param[in] lower_case_table_names_arg lower case table names
277-
@param[in] psi_mutex_key_arg mutex key
278286
@param[in] default_table_encryption_arg default_table_encryption
279287
@param[in] recovery_endpoints_arg recovery endpoints
280288
@param[in] view_change_uuid_arg view change uuid
281289
advertised
282290
@param[in] allow_single_leader flag indicating whether or
283291
not to use single-leader behavior
292+
@param[in] psi_mutex_key_arg mutex key
284293
*/
285294
Group_member_info(const char *hostname_arg, uint port_arg,
286295
const char *uuid_arg, int write_set_extraction_algorithm,
@@ -707,8 +716,8 @@ class Group_member_info : public Plugin_gcs_message {
707716
uint port;
708717
std::string uuid;
709718
Group_member_status status;
710-
Gcs_member_identifier *gcs_member_id;
711-
Member_version *member_version;
719+
Gcs_member_identifier *gcs_member_id{nullptr};
720+
Member_version *member_version{nullptr};
712721
std::string executed_gtid_set;
713722
std::string purged_gtid_set;
714723
std::string retrieved_gtid_set;
@@ -784,21 +793,32 @@ class Group_member_info_manager_interface {
784793
/**
785794
Retrieves a registered Group member by its uuid
786795
787-
@param[in] uuid uuid to retrieve
788-
@return reference to a copy of Group_member_info. NULL if not managed.
789-
The return value must deallocated by the caller.
796+
@param[in] uuid uuid to retrieve
797+
@param[out] member_info_arg a member info reference local to the
798+
method caller that is updated when the
799+
member is found.
800+
801+
@return true if the member is not found.
802+
false if the member is found.
790803
*/
791-
virtual Group_member_info *get_group_member_info(const std::string &uuid) = 0;
804+
[[NODISCARD]] virtual bool get_group_member_info(
805+
const std::string &uuid, Group_member_info &member_info_arg) = 0;
792806

793807
/**
794808
Retrieves a registered Group member by an index function.
795809
One is free to determine the index function. Nevertheless, it should have
796810
the same result regardless of the member of the group where it is called
797811
798-
@param[in] idx the index
799-
@return reference to a Group_member_info. NULL if not managed
812+
@param[in] idx the index
813+
@param[out] member_info_arg a member info reference local to the
814+
method caller that is updated when the
815+
member is found.
816+
817+
@return true if the member is not found.
818+
false if the member is found.
800819
*/
801-
virtual Group_member_info *get_group_member_info_by_index(int idx) = 0;
820+
[[NODISCARD]] virtual bool get_group_member_info_by_index(
821+
int idx, Group_member_info &member_info_arg) = 0;
802822

803823
/**
804824
Return lowest member version.
@@ -811,12 +831,16 @@ class Group_member_info_manager_interface {
811831
/**
812832
Retrieves a registered Group member by its backbone GCS identifier.
813833
814-
@param[in] id the GCS identifier
815-
@return reference to a copy of Group_member_info. NULL if not managed.
816-
The return value must be deallocated by the caller.
834+
@param[in] id the GCS identifier
835+
@param[out] member_info_arg a member info reference local to the
836+
method caller that is updated when the
837+
member is found.
838+
839+
@return true if the member is not found.
840+
false if the member is found.
817841
*/
818-
virtual Group_member_info *get_group_member_info_by_member_id(
819-
const Gcs_member_identifier &id) = 0;
842+
[[NODISCARD]] virtual bool get_group_member_info_by_member_id(
843+
const Gcs_member_identifier &id, Group_member_info &member_info_arg) = 0;
820844

821845
/**
822846
Returns the member-uuid of the given GCS identifier.
@@ -1003,11 +1027,15 @@ class Group_member_info_manager_interface {
10031027
/**
10041028
Return the group member info for the current group primary
10051029
1006-
@note the returned reference must be deallocated by the caller.
1030+
@param[out] member_info_arg a member info reference local to the
1031+
method caller that is updated when the
1032+
member is found.
10071033
1008-
@return reference to a Group_member_info. NULL if not managed
1034+
@return true if the member is not found.
1035+
false if the member is found.
10091036
*/
1010-
virtual Group_member_info *get_primary_member_info() = 0;
1037+
[[NODISCARD]] virtual bool get_primary_member_info(
1038+
Group_member_info &member_info_arg) = 0;
10111039

10121040
/**
10131041
Check if majority of the group is unreachable
@@ -1132,14 +1160,17 @@ class Group_member_info_manager : public Group_member_info_manager_interface {
11321160

11331161
bool is_member_info_present(const std::string &uuid) override;
11341162

1135-
Group_member_info *get_group_member_info(const std::string &uuid) override;
1163+
[[NODISCARD]] bool get_group_member_info(
1164+
const std::string &uuid, Group_member_info &member_info_arg) override;
11361165

1137-
Group_member_info *get_group_member_info_by_index(int idx) override;
1166+
[[NODISCARD]] bool get_group_member_info_by_index(
1167+
int idx, Group_member_info &member_info_arg) override;
11381168

11391169
Member_version get_group_lowest_online_version() override;
11401170

1141-
Group_member_info *get_group_member_info_by_member_id(
1142-
const Gcs_member_identifier &id) override;
1171+
[[NODISCARD]] bool get_group_member_info_by_member_id(
1172+
const Gcs_member_identifier &id,
1173+
Group_member_info &member_info_arg) override;
11431174

11441175
std::pair<bool, std::string> get_group_member_uuid_from_member_id(
11451176
const Gcs_member_identifier &id) override;
@@ -1193,7 +1224,8 @@ class Group_member_info_manager : public Group_member_info_manager_interface {
11931224

11941225
bool get_primary_member_uuid(std::string &primary_member_uuid) override;
11951226

1196-
Group_member_info *get_primary_member_info() override;
1227+
[[NODISCARD]] bool get_primary_member_info(
1228+
Group_member_info &member_info_arg) override;
11971229

11981230
bool is_majority_unreachable() override;
11991231

plugin/group_replication/src/gcs_event_handlers.cc

Lines changed: 43 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -377,13 +377,10 @@ void Plugin_gcs_events_handler::handle_recovery_message(
377377
*/
378378
disable_read_mode_for_compatible_members(true);
379379
} else {
380-
Group_member_info *member_info =
381-
group_member_mgr->get_group_member_info(member_uuid);
382-
if (member_info != nullptr) {
380+
Group_member_info member_info;
381+
if (!group_member_mgr->get_group_member_info(member_uuid, member_info)) {
383382
LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_MEM_ONLINE,
384-
member_info->get_hostname().c_str(),
385-
member_info->get_port());
386-
delete member_info;
383+
member_info.get_hostname().c_str(), member_info.get_port());
387384

388385
/*
389386
The member is declared as online upon receiving this message
@@ -662,38 +659,42 @@ void Plugin_gcs_events_handler::on_suspicions(
662659
if (!members.empty()) {
663660
for (mit = members.begin(); mit != members.end(); mit++) {
664661
Gcs_member_identifier member = *mit;
665-
Group_member_info *member_info =
666-
group_member_mgr->get_group_member_info_by_member_id(member);
667-
668-
if (member_info == nullptr) // Trying to update a non-existing member
669-
continue; /* purecov: inspected */
662+
Group_member_info member_info;
663+
664+
if (group_member_mgr->get_group_member_info_by_member_id(member,
665+
member_info)) {
666+
LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_MEMBER_INFO_DOES_NOT_EXIST,
667+
"by the Gcs_member_identifier",
668+
member.get_member_id().c_str(),
669+
"REACHABLE/UNREACHABLE notification from group "
670+
"communication engine");
671+
continue; /* purecov: inspected */
672+
}
670673

671674
uit = std::find(tmp_unreachable.begin(), tmp_unreachable.end(), member);
672675
if (uit != tmp_unreachable.end()) {
673-
if (!member_info->is_unreachable()) {
676+
if (!member_info.is_unreachable()) {
674677
LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_MEM_UNREACHABLE,
675-
member_info->get_hostname().c_str(),
676-
member_info->get_port());
678+
member_info.get_hostname().c_str(),
679+
member_info.get_port());
677680
// flag as a member having changed state
678681
m_notification_ctx.set_member_state_changed();
679-
group_member_mgr->set_member_unreachable(member_info->get_uuid());
682+
group_member_mgr->set_member_unreachable(member_info.get_uuid());
680683
}
681684
// remove to not check again against this one
682685
tmp_unreachable.erase(uit);
683686
} else {
684-
if (member_info->is_unreachable()) {
687+
if (member_info.is_unreachable()) {
685688
LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_MEM_REACHABLE,
686-
member_info->get_hostname().c_str(),
687-
member_info->get_port());
689+
member_info.get_hostname().c_str(),
690+
member_info.get_port());
688691
/* purecov: begin inspected */
689692
// flag as a member having changed state
690693
m_notification_ctx.set_member_state_changed();
691-
group_member_mgr->set_member_reachable(member_info->get_uuid());
694+
group_member_mgr->set_member_reachable(member_info.get_uuid());
692695
/* purecov: end */
693696
}
694697
}
695-
696-
delete member_info;
697698
}
698699
}
699700

@@ -790,31 +791,30 @@ void Plugin_gcs_events_handler::get_hosts_from_view(
790791
members.begin();
791792

792793
while (all_members_it != members.end()) {
793-
Group_member_info *member_info =
794-
group_member_mgr->get_group_member_info_by_member_id((*all_members_it));
794+
Group_member_info member_info;
795+
const bool member_not_found =
796+
group_member_mgr->get_group_member_info_by_member_id((*all_members_it),
797+
member_info);
795798
all_members_it++;
796799

797-
if (member_info == nullptr) continue;
800+
if (member_not_found) continue;
798801

799-
hosts_string << member_info->get_hostname() << ":"
800-
<< member_info->get_port();
802+
hosts_string << member_info.get_hostname() << ":" << member_info.get_port();
801803

802804
/**
803805
Check in_primary_mode has been added for safety.
804806
Since primary role is in single-primary mode.
805807
*/
806-
if (member_info->in_primary_mode() &&
807-
member_info->get_role() == Group_member_info::MEMBER_ROLE_PRIMARY) {
808+
if (member_info.in_primary_mode() &&
809+
member_info.get_role() == Group_member_info::MEMBER_ROLE_PRIMARY) {
808810
if (primary_string.rdbuf()->in_avail() != 0) primary_string << ", ";
809-
primary_string << member_info->get_hostname() << ":"
810-
<< member_info->get_port();
811+
primary_string << member_info.get_hostname() << ":"
812+
<< member_info.get_port();
811813
}
812814

813815
if (all_members_it != members.end()) {
814816
hosts_string << ", ";
815817
}
816-
817-
delete member_info;
818818
}
819819
all_hosts.assign(hosts_string.str());
820820
primary_host.assign(primary_string.str());
@@ -1435,13 +1435,12 @@ int Plugin_gcs_events_handler::process_local_exchanged_data(
14351435
Gcs_member_identifier *member_id = exchanged_data_it->first;
14361436
if (data == nullptr) {
14371437
/* purecov: begin inspected */
1438-
Group_member_info *member_info =
1439-
group_member_mgr->get_group_member_info_by_member_id(*member_id);
1440-
if (member_info != nullptr) {
1438+
Group_member_info member_info;
1439+
if (!group_member_mgr->get_group_member_info_by_member_id(*member_id,
1440+
member_info)) {
14411441
LogPluginErr(ERROR_LEVEL, ER_GRP_RPL_DATA_NOT_PROVIDED_BY_MEM,
1442-
member_info->get_hostname().c_str(),
1443-
member_info->get_port());
1444-
delete member_info;
1442+
member_info.get_hostname().c_str(),
1443+
member_info.get_port());
14451444
}
14461445
continue;
14471446
/* purecov: end */
@@ -1690,10 +1689,9 @@ void Plugin_gcs_events_handler::update_member_status(
16901689
for (vector<Gcs_member_identifier>::const_iterator it = members.begin();
16911690
it != members.end(); ++it) {
16921691
Gcs_member_identifier member = *it;
1693-
Group_member_info *member_info =
1694-
group_member_mgr->get_group_member_info_by_member_id(member);
1695-
1696-
if (member_info == nullptr) {
1692+
Group_member_info member_info;
1693+
if (group_member_mgr->get_group_member_info_by_member_id(member,
1694+
member_info)) {
16971695
// Trying to update a non-existing member
16981696
continue;
16991697
}
@@ -1704,18 +1702,16 @@ void Plugin_gcs_events_handler::update_member_status(
17041702
// (the old_status_different_from is not defined or
17051703
// the previous status is different from old_status_different_from)
17061704
if ((old_status_equal_to == Group_member_info::MEMBER_END ||
1707-
member_info->get_recovery_status() == old_status_equal_to) &&
1705+
member_info.get_recovery_status() == old_status_equal_to) &&
17081706
(old_status_different_from == Group_member_info::MEMBER_END ||
1709-
member_info->get_recovery_status() != old_status_different_from)) {
1707+
member_info.get_recovery_status() != old_status_different_from)) {
17101708
/*
17111709
The notification will be handled on the top level handle
17121710
function that calls this one down the stack.
17131711
*/
1714-
group_member_mgr->update_member_status(member_info->get_uuid(), status,
1712+
group_member_mgr->update_member_status(member_info.get_uuid(), status,
17151713
m_notification_ctx);
17161714
}
1717-
1718-
delete member_info;
17191715
}
17201716
}
17211717

plugin/group_replication/src/group_actions/communication_protocol_action.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,13 @@ int Communication_protocol_action::set_consensus_leaders() const {
5353
Gcs_member_identifier const my_gcs_id =
5454
local_member_info->get_gcs_member_id();
5555
if (is_single_primary_mode) {
56-
Group_member_info *primary_info =
57-
group_member_mgr->get_primary_member_info();
58-
if (primary_info == nullptr) {
56+
Group_member_info primary_info;
57+
if (group_member_mgr->get_primary_member_info(primary_info)) {
5958
return 1;
6059
}
6160

6261
Gcs_member_identifier const primary_gcs_id =
63-
primary_info->get_gcs_member_id();
64-
delete primary_info;
62+
primary_info.get_gcs_member_id();
6563
bool const am_i_the_primary = (my_gcs_id == primary_gcs_id);
6664
my_role = (am_i_the_primary ? Group_member_info::MEMBER_ROLE_PRIMARY
6765
: Group_member_info::MEMBER_ROLE_SECONDARY);

plugin/group_replication/src/group_actions/multi_primary_migration_action.cc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,11 @@ int Multi_primary_migration_action::process_action_message(
8282
return 1; /* purecov: inspected */
8383
}
8484

85-
Group_member_info *primary_info = group_member_mgr->get_primary_member_info();
86-
if (primary_info != nullptr) {
87-
primary_uuid.assign(primary_info->get_uuid());
88-
primary_gcs_id.assign(primary_info->get_gcs_member_id().get_member_id());
85+
Group_member_info primary_info;
86+
if (!group_member_mgr->get_primary_member_info(primary_info)) {
87+
primary_uuid.assign(primary_info.get_uuid());
88+
primary_gcs_id.assign(primary_info.get_gcs_member_id().get_member_id());
8989
is_primary = !primary_uuid.compare(local_member_info->get_uuid());
90-
delete primary_info;
9190
}
9291

9392
group_events_observation_manager->register_group_event_observer(this);

0 commit comments

Comments
 (0)