Skip to content

Commit

Permalink
RedisPipeline ignore flush when call dtor from another thread. (#736)
Browse files Browse the repository at this point in the history
#### Why I did it
Because RedisPipeline is not thread safe, in c++ if code call exit() from another thread, the dtor of RedisPipeline will  be called from another thread and trigger a race condition issue.

#### How I did it
RedisPipeline ignore flush when call dtor from another thread.

#### How to verify it
Pass all UT and E2E test cases.

#### Which release branch to backport (provide reason below if selected)

<!--
- Note we only backport fixes to a release branch, *not* features!
- Please also provide a reason for the backporting below.
- e.g.
- [x] 202006
-->

- [ ] 201811
- [ ] 201911
- [ ] 202006
- [ ] 202012
- [ ] 202106
- [ ] 202111

#### Description for the changelog
RedisPipeline ignore flush when call dtor from another thread.

#### Link to config_db schema for YANG module changes
<!--
Provide a link to config_db schema for the table for which YANG model
is defined
Link should point to correct section on https://github.com/Azure/SONiC/wiki/Configuration.
-->

#### A picture of a cute animal (not mandatory but encouraged)
  • Loading branch information
liuh-80 authored and qiluo-msft committed Feb 10, 2023
1 parent c5ed58a commit 3e34309
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion common/redispipeline.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#include "redisreply.h"
#include "rediscommand.h"
#include "dbconnector.h"
#include "logger.h"

#include "unistd.h"
#include "sys/syscall.h"
#define gettid() syscall(SYS_gettid)

namespace swss {

Expand All @@ -18,10 +23,20 @@ class RedisPipeline {
, m_remaining(0)
{
m_db = db->newConnector(NEWCONNECTOR_TIMEOUT);
initializeOwnerTid();
}

~RedisPipeline() {
flush();
if (m_ownerTid == gettid())
{
// call flush from different thread will trigger race condition issue.
flush();
}
else
{
SWSS_LOG_NOTICE("RedisPipeline dtor is called from another thread, possibly due to exit(), Database: %s", getDbName().c_str());
}

delete m_db;
}

Expand Down Expand Up @@ -124,10 +139,16 @@ class RedisPipeline {
return m_db;
}

void initializeOwnerTid()
{
m_ownerTid = gettid();
}

private:
DBConnector *m_db;
std::queue<int> m_expectedTypes;
size_t m_remaining;
long int m_ownerTid;

void mayflush()
{
Expand Down

0 comments on commit 3e34309

Please sign in to comment.