Hi,
I'm trying to write some Ruby bindings for the netsnmp C library, using C. Because of the synch API blocks the Ruby VM as it doesn't natively release the GIL, I had two options: 1) patch and package a custom version of the library where I release the GIL on I/O; 2) use the available async API. I went with option 2.
So far so good. Under small load and perfect network conditions, it all works well. As soon as there are a lot of threads/fds available, I start having weird errors.
The most concerning is not managing to instantiate an IO object from a fileno int. To sum up:
1) I initialize the session structure by calling C function snmp_sess_init, fill it up with the necessary data;
2) I call C function snmp_sess_open with the pointer and another pointer is returned. According to the API documentation, if pointer is null, I can stop right there;
3) accessing some internal data, I can access the fileno, which I can use to instantiate an IO object using IO.for_fd, which I subsequently use for wait events.
Under heavy load, I sometimes get EBADF when calling IO.for_fd. I have the feeling that the socket is not open, or the ID is just an arbitrary ID from a previous use of the structure, I'm not sure.
I was wondering whether this has to do with me calling attach_function on all methods with blocking: true set. I assumed that that meant "operation that does I/O, GIL will be released while native-calling". I'm starting to think that I may have misunderstood the meaning and may incur in wrong behaviour.
So, when is it safe/not safe to set blocking: true? I read the documentation, and the only thing I find is "set to true when the call is blocking".