Skip to content

Clean up and improve Network Events#276

Merged
jsiegle merged 11 commits intoopen-ephys:developmentfrom
tne-lab:network-events-load-fix
Dec 18, 2018
Merged

Clean up and improve Network Events#276
jsiegle merged 11 commits intoopen-ephys:developmentfrom
tne-lab:network-events-load-fix

Conversation

@ethanbb
Copy link
Copy Markdown
Contributor

@ethanbb ethanbb commented Dec 13, 2018

I started out just wanting to fix the port on the editor not updating when loading a signal chain. I found some more issues with the plugin though, so I decided to try fixing them. Sorry for the huge diffs... However, I think you'll find it resolves most of the instability issues that Network Events has suffered from. Also fixes #174.

Overview of changes:

  • Uses RAII wrappers for the context and socket to avoid leaking memory. In particular, similar to the latest Event Broadcaster, the context is shared between instances via a raw pointer but "owned" jointly by all sockets using reference-counted pointers, so that it is destroyed after all instances of the plugin are destroyed. This avoids a crash with ZeroMQ on Windows that happens when a context is destroyed during unloading of a DLL.

  • Avoids destroying the sockets in the main thread (or interacting with them at all except for creating them and passing them to the thread using a lock). ZMQ sockets are not thread-safe, and the call to zmq_close on restart, port change, and shutdown was causing some crashes - possibly the cause of Network Events causes crashes when restarting connection #174.

  • Doesn't block forever on zmq_recv; instead has a timeout of 100 ms. This means possibly some added latency while the thread checks whether it should exit, change port or restart between calls, but these checks should be extremely fast, and the upside is that we don't need to destroy the context each time we need to take one of these actions. The context should typically persist for the lifetime of the program, and creating a new one has a high overhead. As a consequence:

    • When you have two instances of the plugin and then one is deleted, no longer gets into the unfortunate state where the context has been destroyed and there's no way to make a new one for the remaining instance to use.
  • Updates the port label to always show:

    • The actual bound port if connected
    • The string <no cxn> if not connected
    • The string <no zeromq> if it was not compiled with ZeroMQ
  • Allows inputting a "*" as the port to use any available port. The label then updates to show what port was actually selected.

  • If a port change fails and a socket was connected on the previous port, keeps using that port and socket.

  • Sends the status message when receiving an event from the thread rather than the process function, so that it shows up even if acquisition isn't running.

  • Simplifies StringTS significantly - it doesn't really need to be more complicated than a String coupled with a timestamp. In fact, we could use std::pair instead, but having names for the members is nice.

  • Deletes the code related to simulations, since it seemed to be unused. This is all in the last commit since I wasn't sure if it might still be used at some point (maybe for debugging?), so that can be reverted if necessary.

I realize this might take a while to look through, but I hope you get around to it at some point.

@jsiegle
Copy link
Copy Markdown
Member

jsiegle commented Dec 13, 2018

Thanks, this looks awesome! We will test it out and get it merged soon.

@aacuevas
Copy link
Copy Markdown
Collaborator

Indeed. Seems like a much needed cleanup!

Copy link
Copy Markdown
Contributor Author

@ethanbb ethanbb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking a look! I just had a couple more thoughts, see below.

#else
usleep (300 * 1000);
#endif
ScopedPointer<Responder> newResponder = Responder::makeResponder(port);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could make the socket within the thread instead (discarding it without destroying the old one if it fails), and just set urlport here (which we could make atomic) to indicate a port change. Then we wouldn't need nextResponder or the lock. I did it this way so that the caller would immediately know whether the change was successful, but that's actually not a big deal since the thread can just update the port on the editor if the switch fails.

responder = nullptr;
urlport = 5556;
threadRunning = false;
if (!setNewListeningPort(5556))
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we changed setNewListeningPort to not create the socket and return feedback right away, we couldn't do this, so maybe it would be better to just choose the port automatically by inputting 0. Of course loading a signal chain would still switch the port to the saved value, if possible.

unsigned char* buffer = new unsigned char[MAX_MESSAGE_LENGTH];
int result = -1;
ScopedPointer<Responder> responder;
char buffer[MAX_MESSAGE_LENGTH];
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be a HeapBlock rather than an array on the stack, actually. I was thinking I could use a plain array since the size never changes, but I wasn't considering the general rule that large arrays should be on the heap.

@ethanbb
Copy link
Copy Markdown
Contributor Author

ethanbb commented Dec 17, 2018

I'm going to go ahead and make another commit with these changes, unless anyone disagrees or wants to discuss them further.

@jsiegle jsiegle merged commit 537bfff into open-ephys:development Dec 18, 2018
@jsiegle
Copy link
Copy Markdown
Member

jsiegle commented Dec 18, 2018

Works beautifully, thanks again for this!

@ethanbb
Copy link
Copy Markdown
Contributor Author

ethanbb commented Dec 19, 2018

You're welcome! I'm glad you didn't have any issues with it.

@ethanbb ethanbb deleted the network-events-load-fix branch December 19, 2018 22:09
@ethanbb ethanbb restored the network-events-load-fix branch December 19, 2018 22:10
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.

3 participants