Skip to content

Commit

Permalink
Avoid possible GC allocations in MongoCursor.~this. Fixes #2793.
Browse files Browse the repository at this point in the history
This adds a check to the destructor to avoid running into an InvalidMemoryOperationError and instead outputs a more descriptive error message without crashing. This also swaps back the order of operations in killCursors() so that no connection to the server gets allocated by the call if the cursor has already been killed.
  • Loading branch information
s-ludwig committed Mar 25, 2024
1 parent 7ea145c commit ddd5225
Showing 1 changed file with 21 additions and 3 deletions.
24 changes: 21 additions & 3 deletions mongodb/vibe/db/mongo/cursor.d
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,22 @@ struct MongoCursor(DocType = Bson) {

~this() @safe
{
import core.memory : GC;

if( m_data && --m_data.refCount == 0 ){
try {
m_data.killCursors();
// avoid InvalidMemoryOperation errors in case the cursor was
// leaked to the GC
if (m_data.alive && GC.inFinalizer) {
logError("MongoCursor instance that has not been fully processed leaked to the GC!");
try throw new Exception("");
catch (Exception e) {
try () @trusted { logError("%s", e.info); } ();
catch (Exception e2) logError(" ... failed to generate stack trace");
}
} else {
m_data.killCursors();
}
} catch (MongoException e) {
logWarn("MongoDB failed to kill cursors: %s", e.msg);
logDiagnostic("%s", (() @trusted => e.toString)());
Expand Down Expand Up @@ -288,6 +301,7 @@ struct MongoCursor(DocType = Bson) {
/// interface because we still have code for legacy (<3.6) MongoDB servers,
/// which may still used with the old legacy overloads.
private interface IMongoCursorData(DocType) {
@property bool alive() @safe nothrow;
bool empty() @safe; /// Range implementation
long index() @safe; /// Range implementation
DocType front() @safe; /// Range implementation
Expand Down Expand Up @@ -326,6 +340,8 @@ private deprecated abstract class LegacyMongoCursorData(DocType) : IMongoCursorD
long m_limit = 0;
}

@property bool alive() @safe nothrow { return m_cursor != 0; }

final bool empty()
@safe {
if (!m_iterationStarted) startIterating();
Expand Down Expand Up @@ -390,8 +406,8 @@ private deprecated abstract class LegacyMongoCursorData(DocType) : IMongoCursorD

final void killCursors()
@safe {
auto conn = m_client.lockConnection();
if (m_cursor == 0) return;
auto conn = m_client.lockConnection();
conn.killCursors(m_collection, () @trusted { return (&m_cursor)[0 .. 1]; } ());
m_cursor = 0;
}
Expand Down Expand Up @@ -448,6 +464,8 @@ private class MongoFindCursor(DocType) : IMongoCursorData!DocType {
m_database = command["$db"].opt!string;
}

@property bool alive() @safe nothrow { return m_cursor != 0; }

bool empty()
@safe {
if (!m_iterationStarted) startIterating();
Expand Down Expand Up @@ -515,8 +533,8 @@ private class MongoFindCursor(DocType) : IMongoCursorData!DocType {

final void killCursors()
@safe {
auto conn = m_client.lockConnection();
if (m_cursor == 0) return;
auto conn = m_client.lockConnection();
conn.killCursors(m_ns, () @trusted { return (&m_cursor)[0 .. 1]; } ());
m_cursor = 0;
}
Expand Down

0 comments on commit ddd5225

Please sign in to comment.