I have an application written in C++/CLI that uses a library written in C#. The application was written using standard socket APIs and uses select() to multiplex a bunch of ordinary non-async sockets. However, the third party library uses .NET sockets and uses the asynchronous results and callbacks.
Here’s the scenario: I create a bunch of regular sockets in the main thread (a C++/CLI application that uses mostly native-style code). I create the third party library vendor’s C# “session” object which, internally, has a bunch of asynchronous sockets from the .NET classes.
What I noticed was that if I put a NULL timeout parameter into select() in the main thread in which I instantiate the C# “session” object, that no asynchronous callbacks are made at all for their .NET sockets. If I use a time-out of, say, 1-second, and no other activity happens on my non-async sockets, then no async-socket callbacks are delivered until select() times out.
Somehow, select() is preventing the callbacks to happen for the .NET sockets. How do I avoid this? Is there some alternative polling method I can use for the old sockets that would still allow the .NET sockets to have their asynchronous callbacks delivered?
I found the solution.
In AsyncCallbacks used in .NET, you cannot have any functions that block at all, including send()/recv() functions — even if they are non-blocking[1] (at least according to my own tests.) When a blocking function is called in an AsyncCallback, the behavior is undefined. Once I got rid of this “undefinedness” from the code, things started working as normal.
I re-templatized my classes by writing some policy classes that swapped out select() for WaitForMultipleObjectsEx() and solved the issue by putting a SetEvent() in the AsyncCallback to trigger the multiplexing. This seemed to solve most of the issues.
[1] Edit: See below comment. Whether I used send() on a non-blocking or blocking socket didn’t seem to make a difference with regards to “breaking things” and going into undefined behaviors.