Skip to content

Commit af56a61

Browse files
authored
Fix fpmsyncd crash during pfcwd/test_pfcwd_warm_reboot.py worm reboot issue (#3746)
Fix fpmsyncd crash during warm reboot issue Why I did it The SONiC management test case pfcwd/test_pfcwd_warm_reboot.py failed due to a crash in fpmsyncd during the warm reboot process. The crash occurred when fpmsyncd received the warm reboot signal and invoked the WarmStartHelper::checkAndStart() method. At that moment, the m_syncTable inside WarmStartHelper pointed to an invalid route table, which triggered a segmentation fault (SIGSEGV). Root Cause: In the constructor of RouteSync, the initialization of m_warmStartHelper depends on m_routeTable being initialized first. However, in the class declaration, m_warmStartHelper is listed before m_routeTable. In C++, member variables are initialized in the order they are declared in the class—not in the order specified in the constructor’s initializer list. As a result, m_warmStartHelper is initialized before m_routeTable, leading to m_warmStartHelper referencing an uninitialized route table.
1 parent 80932db commit af56a61

4 files changed

Lines changed: 30 additions & 21 deletions

File tree

fpmsyncd/fpmsyncd.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,11 @@ int main(int argc, char **argv)
141141
}
142142

143143
/* If warm-restart feature is enabled, execute 'restoration' logic */
144-
bool warmStartEnabled = sync.m_warmStartHelper.checkAndStart();
144+
bool warmStartEnabled = sync.getWarmStartHelper().checkAndStart();
145145
if (warmStartEnabled)
146146
{
147147
/* Obtain warm-restart timer defined for routing application */
148-
time_t warmRestartIval = sync.m_warmStartHelper.getRestartTimer();
148+
time_t warmRestartIval = sync.getWarmStartHelper().getRestartTimer();
149149
if (!warmRestartIval)
150150
{
151151
warmStartTimer.setInterval(timespec{DEFAULT_ROUTING_RESTART_INTERVAL, 0});
@@ -156,7 +156,7 @@ int main(int argc, char **argv)
156156
}
157157

158158
/* Execute restoration instruction and kick off warm-restart timer */
159-
if (sync.m_warmStartHelper.runRestoration())
159+
if (sync.getWarmStartHelper().runRestoration())
160160
{
161161
warmStartTimer.start();
162162
s.addSelectable(&warmStartTimer);
@@ -171,7 +171,7 @@ int main(int argc, char **argv)
171171
}
172172
else
173173
{
174-
sync.m_warmStartHelper.setState(WarmStart::WSDISABLED);
174+
sync.getWarmStartHelper().setState(WarmStart::WSDISABLED);
175175
}
176176

177177
gSelectTimeout = INFINITE;
@@ -209,7 +209,7 @@ int main(int argc, char **argv)
209209
}
210210
else if (temps == &eoiuCheckTimer)
211211
{
212-
if (sync.m_warmStartHelper.inProgress())
212+
if (sync.getWarmStartHelper().inProgress())
213213
{
214214
if (eoiuFlagsSet(bgpStateTable))
215215
{
@@ -308,7 +308,7 @@ int main(int argc, char **argv)
308308
sync.onRouteResponse(key, fieldValues);
309309
}
310310
}
311-
else if (!warmStartEnabled || sync.m_warmStartHelper.isReconciled())
311+
else if (!warmStartEnabled || sync.getWarmStartHelper().isReconciled())
312312
{
313313
flushPipeline(pipeline);
314314
}

fpmsyncd/routesync.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ class RouteSync : public NetMsg
8181
m_fpmInterface = nullptr;
8282
}
8383

84-
WarmStartHelper m_warmStartHelper;
84+
WarmStartHelper& getWarmStartHelper()
85+
{
86+
return m_warmStartHelper;
87+
}
8588

8689
private:
8790
/* ZMQ client */
@@ -94,6 +97,8 @@ class RouteSync : public NetMsg
9497
ProducerStateTable m_vnet_routeTable;
9598
/* vnet vxlan tunnel table */
9699
ProducerStateTable m_vnet_tunnelTable;
100+
/* Warm start helper */
101+
WarmStartHelper m_warmStartHelper;
97102
/* srv6 mySid table */
98103
ProducerStateTable m_srv6MySidTable;
99104
/* srv6 sid list table */

tests/mock_tests/fpmsyncd/test_routesync.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,19 +1026,6 @@ TEST_F(FpmSyncdResponseTest, TestGetNextHopWt)
10261026
EXPECT_EQ(m_mockRouteSync.getNextHopWt(test_route.get()), "1,1");
10271027
}
10281028

1029-
/**
1030-
* Unit tests for warm restart route handling functionality
1031-
*
1032-
*/
1033-
1034-
class TestableRouteSync : public RouteSync
1035-
{
1036-
public:
1037-
TestableRouteSync(RedisPipeline *pipeline) : RouteSync(pipeline) {}
1038-
1039-
WarmStartHelper& getWarmStartHelper() { return m_warmStartHelper; }
1040-
};
1041-
10421029
class WarmRestartRouteSyncTest : public ::testing::Test
10431030
{
10441031
public:
@@ -1057,7 +1044,7 @@ class WarmRestartRouteSyncTest : public ::testing::Test
10571044

10581045
shared_ptr<swss::DBConnector> m_db = make_shared<swss::DBConnector>("APPL_DB", 0);
10591046
shared_ptr<RedisPipeline> m_pipeline = make_shared<RedisPipeline>(m_db.get());
1060-
TestableRouteSync m_testRouteSync{m_pipeline.get()};
1047+
RouteSync m_testRouteSync{m_pipeline.get()};
10611048
};
10621049

10631050
TEST_F(WarmRestartRouteSyncTest, TestRouteMessageHandlingWarmRestartNotInProgress)

tests/test_warm_reboot.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2475,6 +2475,23 @@ def test_TunnelMgrdWarmRestart(self, dvs):
24752475
assert nadd == 0
24762476
assert ndel == 0
24772477

2478+
def test_FpmsyncdWarmRestart(self, dvs):
2479+
# This test aims to improve code coverage in fpmsyncd.
2480+
warm_restart_set(dvs, "system", "true")
2481+
warm_restart_set(dvs, "bgp", "true")
2482+
2483+
# set restore count
2484+
db = swsscommon.DBConnector(6, dvs.redis_sock, 0)
2485+
tbl = swsscommon.Table(db, "WARM_RESTART_ENABLE_TABLE")
2486+
fvs = swsscommon.FieldValuePairs([("restore_count", "0")])
2487+
tbl.set("bgp", fvs)
2488+
2489+
# Stop fpmsyncd
2490+
dvs.stop_fpmsyncd()
2491+
2492+
# Start fpmsyncd
2493+
dvs.start_fpmsyncd()
2494+
24782495
# Add Dummy always-pass test at end as workaroud
24792496
# for issue when Flaky fail on final test it invokes module tear-down before retrying
24802497
def test_nonflaky_dummy():

0 commit comments

Comments
 (0)