Hi,

I'm trying to put together a helgrind suppression file for use with zmq programs. There is lots of noise coming from helgrind without suppressions due to the lock-free stuff going on in zmq.

I have a bunch of suppressions at the moment that get rid of some or the more common errors. While I was working on this, I came across a few that are puzzling, and I'm looking for advice whether these are false positives or real. I've attached a trivial program that communicates between two threads with REQ/REP, each thread using its own context.

The server thread just echoes back what it receives, and the client thread checks that what it received matches what it sent.

This program works with zero errors when I run it with the attached suppression file:

$ valgrind --tool=helgrind --suppressions=suppress ./a.out
...
==4671== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 790 from 483)

The client thread sends a string of 29 bytes:

const int len = 29;                   // Noise happens if len >= 30
const std::string payload(len, 'a');
...
zmq::message_t request(payload.size());
memcpy((void *)request.data(), payload.c_str(), payload.size());
socket.send(request);

Now, as soon as the length of the string is 30 bytes or more, I get a large number of potential races reported by helgrind. It looks like the string contents spill over onto the heap at that point, so the zmq code takes a different path.

I'm seeing races in zmq::msg_t::data() and memcpy(), as well as a race in zmq::msg_t::close().

My question is whether these are false positives or not. I'd much appreciate any input you might have. (I'm not familiar with the zmq code base, so I'm hoping that someone who knows the code might be able to help.)

I've attached the program and the suppression file I used.

Compile with (gcc 4.9):

c++ -g -std=c++11 main.cpp -lzmq -lpthread

and run as above.

Thanks,

Michi.


#include <zmq.hpp>
#include <string>
#include <thread>

const int linger_time = 2000;

void echo_thread()
{
    zmq::context_t context;
    zmq::socket_t socket(context, ZMQ_REP);
    socket.setsockopt(ZMQ_LINGER, &linger_time, sizeof(linger_time));
    socket.bind("ipc://mysocket");

    zmq::message_t msg;
    socket.recv(&msg);
    socket.send(msg);
}

const int len = 29;                   // Noise happens if len >= 30
const std::string payload(len, 'a');

int main()
{
    std::thread t{echo_thread};

    zmq::context_t context;
    zmq::socket_t socket(context, ZMQ_REQ);
    socket.setsockopt(ZMQ_LINGER, &linger_time, sizeof(linger_time));
    socket.connect("ipc://mysocket");

    zmq::message_t request(payload.size());
    memcpy((void *)request.data(), payload.c_str(), payload.size());
    socket.send(request);

    zmq::message_t reply;
    socket.recv(&reply);
    std::string r((const char*)reply.data(), reply.size());
    assert (r == payload);

    t.join();
}
{
    zmq_epoll_race
    Helgrind:Race
    ...
    fun:_ZN3zmq7epoll_t4loopEv
    ...
}

{
    zmq_connect_race
    Helgrind:Race
    fun:_ZNSt6localeC1Ev
    fun:_ZN3zmq13ipc_address_t9to_stringERSs
    fun:_ZNK3zmq9address_t9to_stringERSs
    fun:_ZN3zmq13socket_base_t7connectEPKc
    ...
}

{
    zmq_bind_race
    Helgrind:Race
    ...
    fun:_ZN3zmq14ipc_listener_t11set_addressEPKc
    fun:_ZN3zmq13socket_base_t4bindEPKc
    fun:_ZN3zmq8socket_t4bindEPKc
    ...
}

{
    zmq_recv_race
    Helgrind:Race
    ...
    fun:_ZL9s_recvmsgPN3zmq13socket_base_tEP9zmq_msg_ti
    ...
}

{
    zmq_send_race
    Helgrind:Race
    ...
    fun:_ZL9s_sendmsgPN3zmq13socket_base_tEP9zmq_msg_ti
    ...
}

{
    zmq_term_race
    Helgrind:Race
    ...
    fun:zmq_ctx_term
    ...
}
_______________________________________________
zeromq-dev mailing list
zeromq-dev@lists.zeromq.org
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

Reply via email to