Skip to content

Commit 22f8dc1

Browse files
asfernandesdyemanov
authored andcommitted
Backport complete fix for #8185 - SIGSEGV with WHERE CURRENT OF statement with statement cache turned on
1 parent 41a9856 commit 22f8dc1

6 files changed

+38
-13
lines changed

src/dsql/DsqlRequests.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "../dsql/DsqlRequests.h"
2424
#include "../dsql/dsql.h"
2525
#include "../dsql/DsqlBatch.h"
26-
///#include "../dsql/DsqlStatementCache.h"
26+
#include "../dsql/DsqlStatementCache.h"
2727
#include "../dsql/Nodes.h"
2828
#include "../jrd/Statement.h"
2929
#include "../jrd/req.h"
@@ -179,6 +179,7 @@ void DsqlRequest::destroy(thread_db* tdbb, DsqlRequest* dsqlRequest)
179179
childStatement->setParentRequest(nullptr);
180180
childStatement->setParentDbKey(nullptr);
181181
childStatement->setParentRecVersion(nullptr);
182+
dsqlRequest->req_dbb->dbb_statement_cache->removeStatement(tdbb, childStatement);
182183

183184
// hvlad: lines below is commented out as
184185
// - child is already unlinked from its parent request

src/dsql/DsqlStatementCache.cpp

+31-3
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,44 @@ void DsqlStatementCache::putStatement(thread_db* tdbb, const string& text, USHOR
156156
#endif
157157
}
158158

159+
void DsqlStatementCache::removeStatement(thread_db* tdbb, DsqlStatement* statement)
160+
{
161+
if (const auto cacheKey = statement->getCacheKey())
162+
{
163+
if (const auto entryPtr = map.get(cacheKey))
164+
{
165+
const auto entry = *entryPtr;
166+
167+
entry->dsqlStatement->resetCacheKey();
168+
169+
if (entry->active)
170+
{
171+
entry->dsqlStatement->addRef();
172+
activeStatementList.erase(entry);
173+
}
174+
else
175+
{
176+
inactiveStatementList.erase(entry);
177+
cacheSize -= entry->size;
178+
}
179+
180+
map.remove(entry->key);
181+
}
182+
}
183+
}
184+
159185
void DsqlStatementCache::statementGoingInactive(Firebird::RefStrPtr& key)
160186
{
161187
const auto entryPtr = map.get(key);
162188

163189
if (!entryPtr)
164-
{
165-
fb_assert(false);
166190
return;
167-
}
168191

169192
const auto entry = *entryPtr;
170193

171194
fb_assert(entry->active);
172195
entry->active = false;
196+
entry->dsqlStatement->addRef();
173197
entry->size = entry->dsqlStatement->getSize(); // update size
174198

175199
inactiveStatementList.splice(inactiveStatementList.end(), activeStatementList, entry);
@@ -192,6 +216,9 @@ void DsqlStatementCache::purge(thread_db* tdbb, bool releaseLock)
192216
entry.dsqlStatement->resetCacheKey();
193217
}
194218

219+
for (auto& entry : inactiveStatementList)
220+
entry.dsqlStatement->resetCacheKey();
221+
195222
map.clear();
196223
activeStatementList.clear();
197224
inactiveStatementList.clear();
@@ -273,6 +300,7 @@ void DsqlStatementCache::shrink()
273300
while (cacheSize > maxCacheSize && !inactiveStatementList.isEmpty())
274301
{
275302
const auto& front = inactiveStatementList.front();
303+
front.dsqlStatement->resetCacheKey();
276304
map.remove(front.key);
277305
cacheSize -= front.size;
278306
inactiveStatementList.erase(inactiveStatementList.begin());

src/dsql/DsqlStatementCache.h

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class DsqlStatementCache final : public Firebird::PermanentStorage
106106
void putStatement(thread_db* tdbb, const Firebird::string& text, USHORT clientDialect, bool isInternalRequest,
107107
Firebird::RefPtr<DsqlStatement> dsqlStatement);
108108

109+
void removeStatement(thread_db* tdbb, DsqlStatement* statement);
109110
void statementGoingInactive(Firebird::RefStrPtr& key);
110111

111112
void purge(thread_db* tdbb, bool releaseLock);

src/dsql/DsqlStatements.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,8 @@ int DsqlStatement::release()
6565
{
6666
if (cacheKey)
6767
{
68-
refCnt = ++refCounter;
69-
auto key = cacheKey;
70-
cacheKey = nullptr;
71-
dsqlAttachment->dbb_statement_cache->statementGoingInactive(key);
68+
dsqlAttachment->dbb_statement_cache->statementGoingInactive(cacheKey);
69+
refCnt = refCounter;
7270
}
7371
else
7472
{

src/dsql/DsqlStatements.h

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class DsqlStatement : public Firebird::PermanentStorage
135135
const dsql_par* getEof() const { return eof; }
136136
void setEof(dsql_par* value) { eof = value; }
137137

138+
Firebird::RefStrPtr getCacheKey() { return cacheKey; }
138139
void setCacheKey(Firebird::RefStrPtr& value) { cacheKey = value; }
139140
void resetCacheKey() { cacheKey = nullptr; }
140141

src/dsql/dsql.cpp

+1-5
Original file line numberDiff line numberDiff line change
@@ -639,11 +639,7 @@ static RefPtr<DsqlStatement> prepareStatement(thread_db* tdbb, dsql_dbb* databas
639639
if (!isInternalRequest && dsqlStatement->mustBeReplicated())
640640
dsqlStatement->setOrgText(text, textLength);
641641

642-
const bool basedOnCursor =
643-
(dsqlStatement->getType() == DsqlStatement::TYPE_UPDATE_CURSOR ||
644-
dsqlStatement->getType() == DsqlStatement::TYPE_DELETE_CURSOR);
645-
646-
if (isStatementCacheActive && dsqlStatement->isDml() && !basedOnCursor)
642+
if (isStatementCacheActive && dsqlStatement->isDml())
647643
{
648644
database->dbb_statement_cache->putStatement(tdbb,
649645
textStr, clientDialect, isInternalRequest, dsqlStatement);

0 commit comments

Comments
 (0)