Skip to content

Fix DATE/TIMESTAMP/TIMESTAMP_TZ ref leak in Python binding - #79

Merged
adsharma merged 1 commit into
LadybugDB:mainfrom
adsharma:fix-datetime-ref-leak
Nov 4, 2026
Merged

adsharma merged 1 commit into
LadybugDB:mainfrom
adsharma:fix-datetime-ref-leak

Conversation

@adsharma

@adsharma adsharma commented Nov 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #78.

PyDate_FromDate, PyDateTime_FromDateAndTime and PyDateTimeAPI->DateTime_FromDateAndTime each return a new reference. Wrapping them with py::cast<py::object>(PyObject*) treats the pointer as borrowed and adds another reference, leaking one Python object per DATE / TIMESTAMP (all precisions) / TIMESTAMP_TZ value returned via get_next / get_all / get_n / rows_as_dict / iteration (including inside LIST / STRUCT / node / rel).

This steals the new reference with py::reinterpret_steal<py::object> instead, propagating the Python error when construction fails.

Verified locally against an incremental release build: the issue's repro now reports 0.00 objects left per value for all types and refcount 1 for a singly-held value (was 1.00 leaked per value and refcount 2).

PyDate_FromDate, PyDateTime_FromDateAndTime and
PyDateTimeAPI->DateTime_FromDateAndTime each return a new reference.
Wrapping them with py::cast<py::object>(PyObject*) treats the pointer as
borrowed and adds another reference, leaking one Python object per value
returned via get_next/get_all/get_n/rows_as_dict/iteration (including inside
LIST/STRUCT/node/rel).

Steal the new reference with py::reinterpret_steal instead, propagating the
Python error when construction fails.

Fixes LadybugDB#78
@adsharma
adsharma merged commit dbccb70 into LadybugDB:main Nov 4, 2026
2 checks passed
@adsharma
adsharma deleted the fix-datetime-ref-leak branch November 4, 2026 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: get_next / get_all / rows_as_dict leak every DATE, TIMESTAMP and TIMESTAMP_TZ value (new reference wrapped with py::cast)

1 participant