Skip to content

Commit 863b69c

Browse files
author
Shuotian Cheng
authored
[teamsyncd]: Fix bug when removing selectable in select function (#665)
In the current implementation, the selectable is removed inside the select() function. However, the select function will retrieve multiple file descriptors at one time. If the file descriptor is removed, it will cause segmentation fault. Signed-off-by: Shu0T1an ChenG <[email protected]>
1 parent 2c83b68 commit 863b69c

File tree

3 files changed

+53
-18
lines changed

3 files changed

+53
-18
lines changed

teamsyncd/teamsync.cpp

+40-12
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,34 @@ TeamSync::TeamSync(DBConnector *db, DBConnector *stateDb, Select *select) :
2424
{
2525
}
2626

27+
void TeamSync::doSelectableTask()
28+
{
29+
/* Start to track the new team instances */
30+
for (auto s : m_selectablesToAdd)
31+
{
32+
m_select->addSelectable(m_teamSelectables[s].get());
33+
}
34+
35+
m_selectablesToAdd.clear();
36+
37+
/* No longer track the deprecated team instances */
38+
for (auto s : m_selectablesToRemove)
39+
{
40+
m_select->removeSelectable(m_teamSelectables[s].get());
41+
m_teamSelectables.erase(s);
42+
}
43+
44+
m_selectablesToRemove.clear();
45+
}
46+
2747
void TeamSync::onMsg(int nlmsg_type, struct nl_object *obj)
2848
{
2949
struct rtnl_link *link = (struct rtnl_link *)obj;
3050
if ((nlmsg_type != RTM_NEWLINK) && (nlmsg_type != RTM_DELLINK))
3151
return;
3252

3353
string lagName = rtnl_link_get_name(link);
54+
3455
/* Listens to LAG messages */
3556
char *type = rtnl_link_get_type(link);
3657
if (!type || (strcmp(type, TEAM_DRV_NAME) != 0))
@@ -63,35 +84,40 @@ void TeamSync::addLag(const string &lagName, int ifindex, bool admin_state,
6384
lagName.c_str(), admin_state ? "up" : "down", oper_state ? "up" : "down");
6485

6586
/* Return when the team instance has already been tracked */
66-
if (m_teamPorts.find(lagName) != m_teamPorts.end())
87+
if (m_teamSelectables.find(lagName) != m_teamSelectables.end())
6788
return;
6889

69-
/* Start track the team instance */
70-
auto sync = make_shared<TeamPortSync>(lagName, ifindex, &m_lagMemberTable);
71-
m_select->addSelectable(sync.get());
72-
m_teamPorts[lagName] = sync;
73-
7490
fvVector.clear();
7591
FieldValueTuple s("state", "ok");
7692
fvVector.push_back(s);
7793
m_stateLagTable.set(lagName, fvVector);
94+
95+
/* Create the team instance */
96+
auto sync = make_shared<TeamPortSync>(lagName, ifindex, &m_lagMemberTable);
97+
m_teamSelectables[lagName] = sync;
98+
m_selectablesToAdd.insert(lagName);
7899
}
79100

80101
void TeamSync::removeLag(const string &lagName)
81102
{
103+
/* Delete all members */
104+
auto selectable = m_teamSelectables[lagName];
105+
for (auto it : selectable->m_lagMembers)
106+
{
107+
m_lagMemberTable.del(lagName + ":" + it.first);
108+
}
109+
82110
/* Delete the LAG */
83111
m_lagTable.del(lagName);
84112

85113
SWSS_LOG_INFO("Remove %s", lagName.c_str());
86114

87115
/* Return when the team instance hasn't been tracked before */
88-
if (m_teamPorts.find(lagName) == m_teamPorts.end())
116+
if (m_teamSelectables.find(lagName) == m_teamSelectables.end())
89117
return;
90118

91-
/* No longer track the current team instance */
92-
m_select->removeSelectable(m_teamPorts[lagName].get());
93-
m_teamPorts.erase(lagName);
94119
m_stateLagTable.del(lagName);
120+
m_selectablesToRemove.insert(lagName);
95121
}
96122

97123
const struct team_change_handler TeamSync::TeamPortSync::gPortChangeHandler = {
@@ -114,7 +140,8 @@ TeamSync::TeamPortSync::TeamPortSync(const string &lagName, int ifindex,
114140
}
115141

116142
int err = team_init(m_team, ifindex);
117-
if (err) {
143+
if (err)
144+
{
118145
team_free(m_team);
119146
m_team = NULL;
120147
SWSS_LOG_ERROR("Unable to init team socket");
@@ -123,7 +150,8 @@ TeamSync::TeamPortSync::TeamPortSync(const string &lagName, int ifindex,
123150
}
124151

125152
err = team_change_handler_register(m_team, &gPortChangeHandler, this);
126-
if (err) {
153+
if (err)
154+
{
127155
team_free(m_team);
128156
m_team = NULL;
129157
SWSS_LOG_ERROR("Unable to register port change event");

teamsyncd/teamsync.h

+11-6
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ class TeamSync : public NetMsg
1818
public:
1919
TeamSync(DBConnector *db, DBConnector *stateDb, Select *select);
2020

21-
/*
22-
* Listens to RTM_NEWLINK and RTM_DELLINK to undestand if there is a new
23-
* team device
24-
*/
21+
/* Listen to RTM_NEWLINK, RTM_DELLINK to track team devices */
2522
virtual void onMsg(int nlmsg_type, struct nl_object *obj);
2623

24+
/* Handle all selectables add/removal events */
25+
void doSelectableTask();
26+
2727
class TeamPortSync : public Selectable
2828
{
2929
public:
@@ -35,6 +35,8 @@ class TeamSync : public NetMsg
3535
int getFd() override;
3636
void readData() override;
3737

38+
/* member_name -> enabled|disabled */
39+
std::map<std::string, bool> m_lagMembers;
3840
protected:
3941
int onChange();
4042
static int teamdHandler(struct team_handle *th, void *arg,
@@ -45,7 +47,6 @@ class TeamSync : public NetMsg
4547
struct team_handle *m_team;
4648
std::string m_lagName;
4749
int m_ifindex;
48-
std::map<std::string, bool> m_lagMembers; /* map[ifname] = status (enabled|disabled) */
4950
};
5051

5152
protected:
@@ -58,7 +59,11 @@ class TeamSync : public NetMsg
5859
ProducerStateTable m_lagTable;
5960
ProducerStateTable m_lagMemberTable;
6061
Table m_stateLagTable;
61-
std::map<std::string, std::shared_ptr<TeamPortSync> > m_teamPorts;
62+
63+
/* Store selectables needed to be updated in doSelectableTask function */
64+
std::set<std::string> m_selectablesToAdd;
65+
std::set<std::string> m_selectablesToRemove;
66+
std::map<std::string, std::shared_ptr<TeamPortSync> > m_teamSelectables;
6267
};
6368

6469
}

teamsyncd/teamsyncd.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ int main(int argc, char **argv)
3535
{
3636
Selectable *temps;
3737
s.select(&temps);
38+
39+
sync.doSelectableTask();
3840
}
3941
}
4042
catch (const std::exception& e)

0 commit comments

Comments
 (0)