Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[mosquitto-dev] Thread race between mosquitto_disconnect and mosquitto_loop_stop

Hi All,

I am having some difficulty shutting down mosquitto client threads cleanly.

Attached is a small test program that does:

1) mosquitto_new()

2) mosquitto_connect()

3) mosquitto_loop_start()

4) mosquitto_disconnect()

5) sleep(1)

6) mosquitto_loop_stop()

If I run the program I get a MOSQ_ERR_INVAL return from mosquitto_loop_stop(). The mosq->threaded state is mosq_ts_none instead of the expected mosq_ts_self. This state gets changed when the mosquitto__thread_main() exists. This function changes the state from mosq_ts_self back to mosq_ts_none on thread exit.

I am stuck on how to deal with this in my code. If I ignore the error from mosquitto_loop_stop() then there is a small amount of memory leaked as the pthread_join() call is never called and this shows up on my valgrind reports.

Even without the sleep() call the program will sometimes fail if the mosquitto__thread_main() manages to exit before the mosquitto_loop_stop() gets called in the main thread. I have noticed this periodic failure on my unit tests.

I think the code in mosquitto__thread_main() that sets mosq->threaded back to mosq_ts_none should be removed or perhaps it needs an extra state for mosq_ts_self_exit.

Happy for someone to point out a better solution :-)

Regards,

Denis
#include <mosquitto.h>
#include <iostream>
#include <unistd.h>

int main()
{
    struct mosquitto *mosq;
    int ret;
    
    mosq = mosquitto_new(nullptr, true, nullptr);

    ret = mosquitto_connect(mosq, "localhost", 1883, 10);
    if (ret != MOSQ_ERR_SUCCESS)
    {
        std::cerr << "mosquitto_connect_async() failed\n";
        return 1;
    }

    ret = mosquitto_loop_start(mosq);
    if (ret != MOSQ_ERR_SUCCESS)
    {
        std::cerr << "mosquitto_loop_start() failed\n";
        return 1;
    }

    ret = mosquitto_disconnect(mosq);
    if (ret != MOSQ_ERR_SUCCESS)
    {
        std::cerr << "mosquitto_disconnect() failed\n";
        return 1;
    }

    // Wait for the disconnect to do something
    sleep(1);
    
    ret = mosquitto_loop_stop(mosq, false);
    if (ret != MOSQ_ERR_SUCCESS)
        std::cerr << "mosquitto_loop_stop() failed\n";

    mosquitto_destroy(mosq);
    
    return 0;
}
    

Back to the top