Benp44
Benp44

Reputation: 1588

ZMQ: "Resource temporarily unavailable" when connecting zmq socket

I'm attempting to use libzmq (4.2.2) via czmqz (4.0.2) to establish an IPC communication channel between a Python program and my C++ application.

I'm using the ZMQ publisher/subscriber pattern, where the Python program binds to a port and publishes messages using pyzmq (16.0.2), and my C++ program uses the zsock class from CZMQ to connect as a subscriber.

The problem is, whenever my subscriber attempts to connect, I get back error code 11, Resource temporarily unavailable. Strangely, this system seems to work just fine on my development machine, but not on the target system I'm deploying to.

The problem occurs on the very first line of initializing the socket in the following abridged method:

bool ZmqSocketWrapper::connectSubscriber(string address)
{
    m_address = address;
    m_pSocket = zsock_new_sub(address.c_str(), "");

    int errorCode = zmq_errno();
    if (errorCode != 0)
    {
        printf(zmq_strerror(errorCode));
        return false;
    }

    return true;
}

This is called as follows:

m_subscriberSocket->connectSubscriber("tcp://127.0.0.1:5555");

And I've also tried other variations, with the same result:

m_subscriberSocket->connectSubscriber("tcp://localhost:23232");
m_subscriberSocket->connectSubscriber("ipc:///tmp/test");

When searching online, it appears that most other people have this problem when attempting to send/receive, so it seems odd that I'm having this when just attempting to open the socket.

A few other details:

Any help much appreciated!

Upvotes: 3

Views: 7024

Answers (1)

user3666197
user3666197

Reputation: 1

Good news is given a pure pyzmq scenario works fine,

the hardware or O/S related issues seem to have been excluded from the trouble list.


Damned bindings ( that blind user-programs by a "high-level" skewed-abstration )

The first thing is,
that some high-level industrialists promoting to escape from native-API remove user-side options.

CZMQ did this for example in that it assumes, that every SUB-side wants to just .connect(), not leaving the reversed .bind()/.connect() choice available. Old good ZeroMQ API always let this option on user and that is fair. Similarly, there are many performance tuning variables that need to get set before a socket-connection is setup, which makes the "high-level" binding more troublesome for distributed-system implementations.

Next is the strange thing with a code running fine on one box and not on another.

My worries would be on user-side responsibility to set LINGER to zero + .close() any such created SUB socket ( which need not happen, if due exception handling is not in place ) before a zmq.Context() instance is safely .term()-inated. This may hang orphans that later cause a real-resource being ( still ) occupied, resulting in errno code 11, Resource temporarily unavailable.

Last but not least - resources are not consumables/disposables

The proposed code cannot better exhibit such resources inefficient behaviour and accumulates all the setup / configuration / tear-down overhead costs per each call. This is a very poor design practice ( while users may meet it in many "schoolbook"-examples ). If interested in more details on efficient distributed-computing arguments, also related to this, may also like this post.

bool ZmqSocketWrapper::connectSubscriber(string address)
{   b_RetFLAG = true;
    m_address = address;
    m_pSocket = zsock_new_sub(address.c_str(), "");

    int errorCode = zmq_errno();
    if (errorCode != 0)
    {
        printf(zmq_strerror(errorCode));
        b_RetFLAG = false;
    }
 // -------------------------------------------------------------
    zsock_destroy( &m_pSocket ); // USER's MANDATORY DUTY PRE-RET
 // -------------------------------------------------------------
    return b_RetFLAG;
}

If indeed in a trouble,

use the native API, where your code is fully controlling the stage.

Upvotes: 2

Related Questions