sccn / liblsl

C++ lsl library for multi-modal time-synched data transmission over the local network
Other
114 stars 67 forks source link

Close and re-open a stream does not work #180

Open mscheltienne opened 1 year ago

mscheltienne commented 1 year ago

Hello, another edge-case issue discovered through the Python API that is probably a bug in the C++ lib since the methods involved are one-line wrappers around the C++ functions.

import time

from pylsl import StreamInlet, StreamInfo, StreamOutlet

sinfo = StreamInfo("test", "Markers", 2, 0.)
outlet = StreamOutlet(sinfo)
inlet = StreamInlet(sinfo)
inlet.open_stream()
time.sleep(0.5)  # https://github.com/sccn/liblsl/issues/176
outlet.push_sample([1, 2])
time.sleep(0.2)
assert inlet.samples_available() == 1
inlet.close_stream()
time.sleep(0.2)
assert not outlet.have_consumers()
inlet.open_stream()
time.sleep(0.5)  # https://github.com/sccn/liblsl/issues/176
assert inlet.samples_available() == 1
assert outlet.have_consumers()
outlet.push_sample([1, 2])
time.sleep(0.2)
assert inlet.samples_available() == 2  # fails, still one sample, no matter the number of push

After re-opening a stream, new pushes on the outlet do not yield any new samples at the inlet. This issue is present on all 3 OS, with version 1.16 of the lib.

cboulay commented 5 months ago

Sorry, it's been a while and I just happened to come by this not to fix but just to say how I think it should work.

inlet.close_stream()
time.sleep(0.2)
assert not outlet.have_consumers()
inlet.open_stream()
time.sleep(0.5)  # https://github.com/sccn/liblsl/issues/176
assert inlet.samples_available() == 1

This is the part that is surprising to me. IMO, when closing the stream, all buffers should be closed/cleared. Thus, opening the stream re-creates the buffers and samples_available() should be 0.

I would expect if instead of opening the old stream, you created a new stream (even with the same info) then this would work as expected.

Maybe the short-term mitigation is to document that a close()d stream should not be reused.

mscheltienne commented 5 months ago

That I agree, but rereading my post, it seems the issue is that no matter the number of new pushes on the outlet, nothing arrives at the inlet (which seems to be poorly demonstrated by the example). Anyway:

document that a close()d stream should not be reused

Agree, that's my mitigation solution for now.