[zeromq-dev] inproc: passing an object pointer between threads causing datarace?? (3.2.2 stable release)

Kah-Chan Low kahchanlow at yahoo.com
Thu Nov 29 15:25:23 CET 2012


Oh God!  Now I am totally confused!

Here's my loop:

for (...) {
  int *n = new int;
  *n = 4;
  *n += 2;
  zmq_socket.send(&n, sizeof(n));
}


Doesn't zmq_send(), which is called by socket_t::send(), make a copy of whatever message that is passed in before returning?
So a different pointer gets passed in and copied in each iteration.  What is wrong with doing that?


int zmq_send (void *s_, const void *buf_, size_t len_, int flags_)
{
    if (!s_ || !((zmq::socket_base_t*) s_)->check_tag ()) {
        errno = ENOTSOCK;
        return -1;
    }
    zmq_msg_t msg;
    int rc = zmq_msg_init_size (&msg, len_);
    if (rc != 0)
        return -1;
    memcpy (zmq_msg_data (&msg), buf_, len_);  // isn't copying done here?

    zmq::socket_base_t *s = (zmq::socket_base_t *) s_;
    rc = s_sendmsg (s, &msg, flags_);
    if (unlikely (rc < 0)) {
        int err = errno;
        int rc2 = zmq_msg_close (&msg);
        errno_assert (rc2 == 0);
        errno = err;
        return -1;
    }

    //  Note the optimisation here. We don't close the msg object as it is
    //  empty anyway. This may change when implementation of zmq_msg_t changes.
    return rc;
}



________________________________
 From: Pieter Hintjens <ph at imatix.com>
To: Kah-Chan Low <kahchanlow at yahoo.com> 
Sent: Thursday, November 29, 2012 8:58 AM
Subject: Re: [zeromq-dev] inproc: passing an object pointer between threads causing datarace?? (3.2.2 stable release)
 

I think you are sending a value that is allocated on the stack, and which is not valid by the time the asynchronous send completes. I suspect the pointer is immediately reallocated in the next iteration. So, yes, it will often not have the correct value.  
Pieter
On Nov 29, 2012 1:18 PM, "Kah-Chan Low" <kahchanlow at yahoo.com> wrote:

Sorry, my last sentence should read " In this case,
>is it possible for the program to output any value other than '6' for '*n'?"
>
>
>Basically I declare n as an int*, and I allocate memory for *n, assign a value to *n, and send the pointer n.
>
>
>int *n = new int; *n = 4; *n += 2; zmq_socket.send(&n, sizeof(n));
>
>
>
>So the pointer value is valid when sending actually takes place. 
>
>________________________________
> From: Pieter Hintjens <ph at imatix.com>
>To: Kah-Chan Low <kahchanlow at yahoo.com>; ZeroMQ development list <zeromq-dev at lists.zeromq.org> 
>Sent: Wednesday, November 28, 2012 11:22 PM
>Subject: Re: [zeromq-dev] inproc: passing an object pointer between threads causing datarace?? (3.2.2 stable release)
> 
>On Tue, Nov 27, 2012 at 10:23 PM, Kah-Chan Low <kahchanlow at yahoo.com> wrote:
>
>> 1. I don't understand the error message above: how does accessing the value
>> of variable n have anything to do with the internals of ZMQ?
>
>It doesn't, as far as I can see.
>
>> 2. Is it possible for the compiler to rearrange the machine instructions
>> such that the assignment of value of n (i.e. *n=4; *n += 2;) occurs after
>> the message has been sent and received on the other thread?  In this case,
>> is it possible for the program to output any value other than '6' for 'n'?
>
>That's very doubtful. However are you not declaring n on the stack?
>Meaning, it will not be valid when the send actually happens.
>
>-Pieter
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20121129/9c383756/attachment.htm>


More information about the zeromq-dev mailing list