eclipse/paho.mqtt.c

A segment error occurred after the conn_lost() was executed

Opened this issue · 1 comments

HI,SIR
A segment fault occurred after the conn_lost() was executed ,
once I called MQTTClient_connect(client, &conn_opts) in conn_lost() function , the programe could re-connect the broker, but immediately a segment fault occured , why, what am I doing wrong.
more information : just now I re-compile this program with gcc and run it on unbuntu desktop system , this program run correctly ,no segment fault . so strange.

My code is :
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "MQTTClient.h"
#include "mqtt_req_proc.h"

// Enable or disable SSL/TLS connection (1 for SSL/TLS, 0 for TCP)
#define USE_SSL 0

#if USE_SSL
#define ADDRESS "ssl://broker.emqx.io:8883"
#else
// #define ADDRESS "tcp://47.106.203.236:1883"
#define ADDRESS "tcp://112.74.85.63:1883"
// #define ADDRESS "b187a1e0.ala.dedicated.aliyun.emqxcloud.cn:1883"
#endif

#define USERNAME "steve"
#define PASSWORD "Zrr_4410693"
#define CLIENTID "c-client"
#define QOS 0
#define PUB_TOPIC "192.168.1.103_internal_service"
#define SUB_TOPIC "192.168.1.103_public_service"
#define TIMEOUT 10000L

MQTTClient_SSLOptions configureSSLOptions()
{
MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
ssl_opts.enableServerCertAuth = 1;
// ssl_opts.trustStore = CA_CERTIFICATE_FILE;
return ssl_opts;
}

void publish(MQTTClient client, char *topic, char *payload)
{
MQTTClient_message message = MQTTClient_message_initializer;
message.payload = payload;
message.payloadlen = strlen(payload);
message.qos = QOS;
message.retained = 1;
MQTTClient_deliveryToken token;
MQTTClient_publishMessage(client, topic, &message, &token);
MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Send %s to topic %s \n", payload, PUB_TOPIC);
}
int request_completed = 0;
int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message)
{
char *payload = message->payload;
// printf("Received %s from %s topic \n", payload, topicName);

    request_completed = 1;
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;

}

void conn_lost(void *context, char *cause)
{
printf("\nConnection lost\n");
printf(" cause: %s\n", cause);
int rc;
MQTTClient client = (MQTTClient )context;

MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
     conn_opts.username = USERNAME;
    conn_opts.password = PASSWORD;
conn_opts.keepAliveInterval = 10;
conn_opts.cleansession = 1;

while (1)
{
            rc= MQTTClient_connect(client, &conn_opts);
	if (rc == MQTTCLIENT_SUCCESS)
	{
		printf("Reconnection Successful\n");
		break;
	}
	else
	{
		printf("Failed to connect, return code %d\n", rc);
	}
	sleep(10);
}

while (1)
{
	if (MQTTClient_subscribe(client, SUB_TOPIC, QOS) == MQTTCLIENT_SUCCESS)
	{
		printf("Resubscribe Successful\n");
		break;
	}
	else
	{
		printf("Resubscribe Failure\n");
	}
	sleep(1);
}

}

int main(int argc, char *argv[])
{
int rc;
MQTTClient client;

     MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);

     
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    conn_opts.username = USERNAME;
    conn_opts.password = PASSWORD;

#if USE_SSL
MQTTClient_SSLOptions ssl_opts = configureSSLOptions();
conn_opts.ssl = &ssl_opts;
#endif
conn_opts.keepAliveInterval = 10;
conn_opts.cleansession = 1;
MQTTClient_setCallbacks(client, client, conn_lost, on_message, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
printf("Failed to connect, return code %d\n", rc);
exit(-1);

    }
    else
    {
            printf("Connected to MQTT Broker!\n");
    }
    // subscribe topic
    MQTTClient_subscribe(client, SUB_TOPIC, QOS);


    while (1)
    {
            if (request_completed)
            {
                    request_completed = 0;
                    publish(client, PUB_TOPIC, res);  
            }
    }
    MQTTClient_unsubscribe(client, TOPIC);
    MQTTClient_disconnect(client, TIMEOUT);
    MQTTClient_destroy(&client);
    return rc;

}

The first thing is that the cause field in the connectionLost callback can be null, so it should be checked for that before printing.

Next, the program should not spend a long time in callbacks, which means no sleeping. The only API call allowed in connectionLost is connect - no subscribe or any other.