sccn / liblsl

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

Getting info on a stream that has become invalid causes deadlock #201

Closed crazy-eddie closed 5 months ago

crazy-eddie commented 1 year ago

If you resolve and build an inlet stream and then that stream dies, calling info never returns. It gets stuck waiting for its thread to finish, which is stuck in epoll_wait with a forever timeout.

Steps to reproduce:

  1. Start an LSL stream. Can use pylsl.examples.SendData
  2. Get a list of all streams with lsl::resolve_streams
  3. Create an lsl::stream_inlet out of the resolved stream.
  4. Kill the stream.
  5. Get the full info from the stream by calling 'info'.

The program will get stuck.

The fix is for the info_receiver to check the return status of buffer.connect, and if it's nullptr to throw buffer.error(). None of the checks that would trigger shutdown or lost on the connection have been done so the only way to know that the stream is now gone is to try to use it, and that's done by the buffer.connect call. If this check is not done then the cancellable_streambuf is given data to send and after that the problem is realized but the cancellable_streambuf is going to try to send its data when its destroyed and this results in an epoll_wait forever on an invalid fd.

In other words, in info_receiver::info_thread on line 55 change:

buffer.connect(conn_.get_tcp_endpoint());

To: if (nullptr == buffer.connect(conn_.get_tcp_endpoint())) {
throw buffer.error(); }