einpoklum
einpoklum

Reputation: 131515

Can zmq::message_t's be reused after being sent?

I'm using ZeroMQ to implement a toy communications protocol; and this is my first time using this framework/library.

Now, in my protocol, multiple consecutive messages get sent by a certain party, all of which have the same size. So - I thought, I'd avoid reallocating them, and just try to refill the message data buffer with different content, e.g.:

zmq::message_t msg { fixed_common_size };
while (some_condition()) {
    my_filling_routine(msg.data(), fixed_common_size);
    the_socket.send(msg);
}

but on the second iteration of this loop, I get a segmentation fault; msg.data() is not nullptr though. It occurred to me, that maybe ZeroMQ cannibalizes the memory somehow, and thus I need to write something like:

zmq::message_t msg { fixed_common_size };
char buffer[fixed_common_size];
while (some_condition()) {
    my_filling_routine(buffer, fixed_common_size);
    msg.rebuild(buffer, fixed_common_size);
    the_socket.send(msg);
}

But I'm sure this causes de-allocation and re-allocation.

So, is it really the case that a rebuild() is necessary, or could it just be some bug in my code?

Note: I'm using Unix sockets, in case the answer depends on that somehow.

Upvotes: 2

Views: 1242

Answers (1)

user3666197
user3666197

Reputation: 1

No, you can't reuse a zmq::message_t's after it was sent.

First, welcome to ZeroMQ, a cool place to be in for practitioners.

The ZeroMQ API warns about these issues quite explicitly. A successful call to zmq_msg_send(), referencing a message-payload, does not mean that the message itself has been actually sent.

It's best you try to imagine that the call just "moves" the responsiblity from your application code to the ZeroMQ engine (inside the factory with a pool-of-IOthreads instantiated inside the Context()-instance ... ).

The zmq_msg_t structure passed to zmq_msg_send() is nullified during the call.

and next better never touch it anytime later as reported above :o)

The maximum "ecological"-bypass of allocator is to re-use the whole-message, as :

If you want to send the same message to multiple sockets you have to copy it using ( e.g. using zmq_msg_copy() ).


A bonus warning on copying ...

plus one more raised point: may copy, but dare to try to modify it after this ...

Avoid modifying message content after a message has been copied with zmq_msg_copy(), doing so can result in undefined behaviour. If what you need is an actual hard copy, allocate a new message using zmq_msg_init_size() and copy the message content using memcpy().

Never access zmq_msg_t members directly, instead always use the zmq_msg-family of functions.

Upvotes: 3

Related Questions