[
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;
}