Commit 49da70b1 authored by Amir MOHAMMADI's avatar Amir MOHAMMADI

Adds a delete method to reader.iter types

The video reader was not closing the video files
when iteration did not finish all the way to the end.

Fixes #14
parent 54da7712
Pipeline #25098 passed with stage
in 12 minutes and 52 seconds
......@@ -480,6 +480,12 @@ static PyMappingMethods PyBobIoVideoReader_Mapping = {
static const char* s_videoreaderiterator(BOB_EXT_MODULE_PREFIX ".reader.iter");
static void PyBobIoVideoReaderIterator_Delete (PyBobIoVideoReaderIteratorObject* self) {
self->iter->reset();
self->iter.reset();
Py_XDECREF((PyObject*)self->pyreader);
}
static PyObject* PyBobIoVideoReaderIterator_Iter (PyBobIoVideoReaderIteratorObject* self) {
return Py_BuildValue("O", self);
}
......@@ -488,9 +494,6 @@ static PyObject* PyBobIoVideoReaderIterator_Next (PyBobIoVideoReaderIteratorObje
if ((*self->iter == self->pyreader->v->end()) ||
(self->iter->cur() == self->pyreader->v->numberOfFrames())) {
self->iter->reset();
self->iter.reset();
Py_XDECREF((PyObject*)self->pyreader);
return 0;
}
......@@ -586,6 +589,7 @@ bool init_BobIoVideoReader(PyObject* module){
PyBobIoVideoReaderIterator_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER;
PyBobIoVideoReaderIterator_Type.tp_new = PyType_GenericNew;
PyBobIoVideoReaderIterator_Type.tp_dealloc = reinterpret_cast<destructor>(PyBobIoVideoReaderIterator_Delete);
PyBobIoVideoReaderIterator_Type.tp_iter = reinterpret_cast<getiterfunc>(PyBobIoVideoReaderIterator_Iter);
PyBobIoVideoReaderIterator_Type.tp_iternext = reinterpret_cast<getiterfunc>(PyBobIoVideoReaderIterator_Next);
......
......@@ -119,6 +119,60 @@ def test_memory_leak():
assert (last - first) / first < 0.003, "Looks like we have a memory leak!"
def test_open_file_leak():
import psutil
import tempfile
import gc
from . import reader
from bob.io.base import save
my_video = numpy.random.random_integers(0, 255, (10, 3, 256 * 4, 256 * 4))
process = psutil.Process()
def open_files_count(path):
return len([f for f in process.open_files() if f.path == path])
with tempfile.NamedTemporaryFile(suffix='.avi') as f:
path = f.name
save(my_video.astype('uint8'), path)
# Get a count before doing anything. This following count is 1 because
# NamedTemporaryFile keeps a pointer to this file. We will check if the
# count goes to 0 in the end!
last_count = open_files_count(path)
# load the video at once and see if the count is constant
load(path)
gc.collect()
new_count = open_files_count(path)
assert new_count == last_count, \
('We did not close all the files when loading the video at once. '
'old count: {}, new count: {}'.format(last_count, new_count))
# iterate over all frames and see if the count is constant
for frame in reader(path):
pass
gc.collect()
new_count = open_files_count(path)
assert new_count == last_count, \
('We did not close all the files when iterating over all frames. '
'old count: {}, new count: {}'.format(last_count, new_count))
# iterate over one frame and see if the count is constant
for frame in reader(path):
break
gc.collect()
new_count = open_files_count(path)
assert new_count == last_count, \
('We did not close all the files when iterating over one frame. '
'old count: {}, new count: {}'.format(last_count, new_count))
count = open_files_count(path)
assert count == 0, 'The temporary file was not closed! {}'.format(count)
def write_unicode_temp_file():
prefix = 'bobtest_straße_'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment