From c459ea31a5a9459900c947afcf5aaa53da3a474d Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Wed, 22 Nov 2017 11:30:25 +0100 Subject: [PATCH 01/46] Allow to include Heap.h into c++ Signed-off-by: Juergen Kosel --- src/Heap.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Heap.h b/src/Heap.h index 165b89fb..6d24c04f 100644 --- a/src/Heap.h +++ b/src/Heap.h @@ -59,6 +59,9 @@ typedef struct size_t max_size; /**< max size the heap has reached in bytes */ } heap_info; +#if defined(__cplusplus) + extern "C" { +#endif void* mymalloc(char*, int, size_t size); void* myrealloc(char*, int, void* p, size_t size); @@ -72,5 +75,8 @@ int HeapDump(FILE* file); int HeapDumpString(FILE* file, char* str); void* Heap_findItem(void* p); void Heap_unlink(char* file, int line, void* p); +#ifdef __cplusplus + } +#endif #endif From bde0406348b254454754c002f67550bc6390cabb Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Thu, 23 Nov 2017 08:44:36 +0100 Subject: [PATCH 02/46] Remove unused function MQTTPacket_free_packet() The function MQTTPacket_free_packet() is not used at all. Eliminating dead code to improve readability. Signed-off-by: Juergen Kosel --- src/MQTTPacket.c | 19 ------------------- src/MQTTPacket.h | 2 -- 2 files changed, 21 deletions(-) diff --git a/src/MQTTPacket.c b/src/MQTTPacket.c index c21a432c..33644912 100644 --- a/src/MQTTPacket.c +++ b/src/MQTTPacket.c @@ -734,22 +734,3 @@ int MQTTPacket_send_publish(Publish* pack, int dup, int qos, int retained, netwo FUNC_EXIT_RC(rc); return rc; } - - -/** - * Free allocated storage for a various packet tyoes - * @param pack pointer to the suback packet structure - */ -void MQTTPacket_free_packet(MQTTPacket* pack) -{ - FUNC_ENTRY; - if (pack->header.bits.type == PUBLISH) - MQTTPacket_freePublish((Publish*)pack); - /*else if (pack->header.type == SUBSCRIBE) - MQTTPacket_freeSubscribe((Subscribe*)pack, 1); - else if (pack->header.type == UNSUBSCRIBE) - MQTTPacket_freeUnsubscribe((Unsubscribe*)pack);*/ - else - free(pack); - FUNC_EXIT; -} diff --git a/src/MQTTPacket.h b/src/MQTTPacket.h index 8bad9551..4f212050 100644 --- a/src/MQTTPacket.h +++ b/src/MQTTPacket.h @@ -253,8 +253,6 @@ int MQTTPacket_send_pubrec(int msgid, networkHandles* net, const char* clientID) int MQTTPacket_send_pubrel(int msgid, int dup, networkHandles* net, const char* clientID); int MQTTPacket_send_pubcomp(int msgid, networkHandles* net, const char* clientID); -void MQTTPacket_free_packet(MQTTPacket* pack); - #if !defined(NO_BRIDGE) #include "MQTTPacketOut.h" #endif From 14270a2b8c70da6114c004d312c1691f8d9f7230 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 4 Dec 2017 10:53:35 +0100 Subject: [PATCH 03/46] Add skeleton of test_issue373 Signed-off-by: Juergen Kosel --- test/CMakeLists.txt | 10 +++ test/test_issue373.c | 181 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 test/test_issue373.c diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3aca80f0..18f803ca 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -449,3 +449,13 @@ SET_TESTS_PROPERTIES( test9-6-offline-buffering-max-buffered-binary-will PROPERTIES TIMEOUT 540 ) + +ADD_EXECUTABLE( + test_issue373 + test_issue373.c +) + +TARGET_LINK_LIBRARIES( + test_issue373 + paho-mqtt3a +) diff --git a/test/test_issue373.c b/test/test_issue373.c new file mode 100644 index 00000000..1d463d5e --- /dev/null +++ b/test/test_issue373.c @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2012, 2017 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + * Contributors: + *******************************************************************************/ + +/** + * @file + * Test for issues 373, 385: Memory leak and segmentation fault during connection lost and reconnect + * + */ + +#include "MQTTAsync.h" +#include +#include +#include "Thread.h" + +#if !defined(_WINDOWS) + #include + #include + #include + #include +#else + #include +#endif + +char unique[50]; // unique suffix/prefix to add to clientid/topic etc + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) + +void usage(void) +{ + printf("help!!\n"); + exit(EXIT_FAILURE); +} + +struct Options +{ + char* connection; /**< connection to system under test. */ + char* proxy_connection; /**< connection to proxy */ + int verbose; + int test_no; +} options = +{ + "iot.eclipse.org:1883", + "localhost:1883", + 0, + 0, +}; + +void getopts(int argc, char** argv) +{ + int count = 1; + + while (count < argc) + { + if (strcmp(argv[count], "--test_no") == 0) + { + if (++count < argc) + options.test_no = atoi(argv[count]); + else + usage(); + } + else if (strcmp(argv[count], "--connection") == 0) + { + if (++count < argc) + options.connection = argv[count]; + else + usage(); + } + else if (strcmp(argv[count], "--proxy_connection") == 0) + { + if (++count < argc) + options.proxy_connection = argv[count]; + else + usage(); + } + else if (strcmp(argv[count], "--verbose") == 0) + options.verbose = 1; + count++; + } +} + + +#define LOGA_DEBUG 0 +#define LOGA_INFO 1 +#include +#include +#include +void MyLog(int LOGA_level, char* format, ...) +{ + static char msg_buf[256]; + va_list args; + struct timeb ts; + + struct tm *timeinfo; + + if (LOGA_level == LOGA_DEBUG && options.verbose == 0) + return; + + ftime(&ts); + timeinfo = localtime(&ts.time); + strftime(msg_buf, 80, "%Y%m%d %H%M%S", timeinfo); + + sprintf(&msg_buf[strlen(msg_buf)], ".%.3hu ", ts.millitm); + + va_start(args, format); + vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), + format, args); + va_end(args); + + printf("%s\n", msg_buf); + fflush(stdout); +} + +void MySleep(long milliseconds) +{ +#if defined(WIN32) || defined(WIN64) + Sleep(milliseconds); +#else + usleep(milliseconds*1000); +#endif +} + +int tests = 0; +int failures = 0; + + +int test_373(struct Options options) +{ + return 0; +} + +void handleTrace(enum MQTTASYNC_TRACE_LEVELS level, char* message) +{ + printf("%s\n", message); +} + +int main(int argc, char** argv) +{ + int* numtests = &tests; + int rc = 0; + int (*tests[])() = { NULL, test_373}; + + sprintf(unique, "%u", rand()); + MyLog(LOGA_INFO, "Random prefix/suffix is %s", unique); + + MQTTAsync_setTraceCallback(handleTrace); + getopts(argc, argv); + + if (options.test_no == 0) + { /* run all the tests */ + for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no) + { + failures = 0; + MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); + rc += tests[options.test_no](options); /* return number of failures. 0 = test succeeded */ + } + } + else + { + MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); + rc = tests[options.test_no](options); /* run just the selected test */ + } + + if (rc == 0) + MyLog(LOGA_INFO, "verdict pass"); + else + MyLog(LOGA_INFO, "verdict fail"); + + return rc; +} From cdd7f0e449a1352ca960e3d96aa276336c341942 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 4 Dec 2017 13:20:10 +0100 Subject: [PATCH 04/46] Add test for issue #373 and #385 This test connects to a broker up to 10 times. As long as the connection is established, 100 message should be published each second. At the end all memory should be freed and no segmentation occurred. Signed-off-by: Juergen Kosel --- test/test_issue373.c | 217 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 209 insertions(+), 8 deletions(-) diff --git a/test/test_issue373.c b/test/test_issue373.c index 1d463d5e..58900343 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -25,13 +25,18 @@ #include "Thread.h" #if !defined(_WINDOWS) - #include - #include - #include - #include +#include +#include +#include +#include #else - #include +#include #endif +#include "Heap.h" // for Heap_get_info +// undefine macros from Heap.h: +#undef malloc +#undef realloc +#undef free char unique[50]; // unique suffix/prefix to add to clientid/topic etc @@ -115,7 +120,7 @@ void MyLog(int LOGA_level, char* format, ...) va_start(args, format); vsnprintf(&msg_buf[strlen(msg_buf)], sizeof(msg_buf) - strlen(msg_buf), - format, args); + format, args); va_end(args); printf("%s\n", msg_buf); @@ -131,13 +136,203 @@ void MySleep(long milliseconds) #endif } +#define assert(a, b, c, d) myassert(__FILE__, __LINE__, a, b, c, d) + int tests = 0; int failures = 0; +int connected = 0; +int pendingMessageCnt = 0; /* counter of messages which are currently queued for publish */ +int pendingMessageCntMax = 0; +int failedPublishCnt = 0; +int goodPublishCnt = 0; +int connectCnt = 0; +int connecting = 0; +void myassert(char* filename, int lineno, char* description, int value, + char* format, ...) +{ + ++tests; + if (!value) + { + va_list args; + + ++failures; + MyLog(LOGA_INFO, "Assertion failed, file %s, line %d, description: %s", filename, + lineno, description); + + va_start(args, format); + vprintf(format, args); + va_end(args); + } + else + MyLog(LOGA_DEBUG, "Assertion succeeded, file %s, line %d, description: %s", + filename, lineno, description); +} + + +void test1373OnFailure(void* context, MQTTAsync_failureData* response) +{ + MyLog(LOGA_INFO, "In connect onFailure callback, context %p", context); + connecting = 0; +} + +void test373OnConnect(void* context, MQTTAsync_successData* response) +{ + connected = 1; + connecting = 0; + connectCnt++; + MyLog(LOGA_INFO, "Established MQTT connection to %s",response->alt.connect.serverURI); + char MqttVersion[40]; + switch (response->alt.connect.MQTTVersion) + { + case MQTTVERSION_3_1: + sprintf(MqttVersion," MQTT version 3.1"); + break; + case MQTTVERSION_3_1_1: + sprintf(MqttVersion, " MQTT version 3.1.1"); + break; + default: + sprintf(MqttVersion, " MQTT version %d",response->alt.connect.MQTTVersion); + } + MyLog(LOGA_INFO, " %s\n",MqttVersion); + MyLog(LOGA_INFO, "connectCnt %d\n",connectCnt); +} + +void test373ConnectionLost(void* context, char* cause) +{ + connected = 0; + MyLog(LOGA_INFO, "Disconnected from MQTT broker reason %s",cause); +} + +void test373DeliveryComplete(void* context, MQTTAsync_token token) +{ + pendingMessageCnt--; +} + +void test373_onWriteSuccess(void* context, MQTTAsync_successData* response) +{ + goodPublishCnt++; +} + +void test373_onWriteFailure(void* context, MQTTAsync_failureData* response) +{ + failedPublishCnt++; +} + +int test373_messageArrived(void* context, char* topicName, int topicLen, MQTTAsync_message* message) +{ + return 0; +} + +static char test373Payload[] = "No one is interested in this payload"; + +int test373SendPublishMessage(MQTTAsync handle,int id) +{ + int rc = 0; + MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; + MQTTAsync_message pubmsg = MQTTAsync_message_initializer; + char topic[ sizeof(unique) + 40]; + + sprintf(topic,"%s/test373/item_%03d",unique,id); + opts.onFailure = test373_onWriteFailure; + opts.onSuccess = test373_onWriteSuccess; + + pubmsg.payload = test373Payload; + pubmsg.payloadlen = sizeof(test373Payload); + pubmsg.qos = 0; + rc = MQTTAsync_sendMessage( handle, topic,&pubmsg,&opts); + if (rc == MQTTASYNC_SUCCESS) + { + pendingMessageCnt++; + if (pendingMessageCnt > pendingMessageCntMax) pendingMessageCntMax = pendingMessageCnt; + } + return rc; +} int test_373(struct Options options) { - return 0; + char* testname = "test373"; + MQTTAsync mqttasyncContext; + MQTTAsync_connectOptions opts = MQTTAsync_connectOptions_initializer; + MQTTAsync_willOptions wopts = MQTTAsync_willOptions_initializer; + int rc = 0; + char clientid[30 + sizeof(unique)]; + heap_info* mqtt_mem = 0; + + sprintf(clientid, "paho-test373-%s", unique); + rc = MQTTAsync_create(&mqttasyncContext, options.proxy_connection, clientid, + MQTTCLIENT_PERSISTENCE_NONE, + NULL); + assert("good rc from create", rc == MQTTASYNC_SUCCESS, "rc was %d \n", rc); + if (rc != MQTTASYNC_SUCCESS) + { + goto exit; + } + opts.connectTimeout = 2; + opts.keepAliveInterval = 20; + opts.cleansession = 0; + opts.MQTTVersion = MQTTVERSION_DEFAULT; + opts.onSuccess = test373OnConnect; + opts.onFailure = test1373OnFailure; + opts.context = mqttasyncContext; + + rc = MQTTAsync_setCallbacks(mqttasyncContext,mqttasyncContext, + test373ConnectionLost, + test373_messageArrived, + test373DeliveryComplete); + if (rc != MQTTASYNC_SUCCESS) + { + goto exit; + } + MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); + while (connectCnt < 10) + { + MyLog(LOGA_INFO, "Connected %d connectCnt %d\n",connected,connectCnt); + mqtt_mem = Heap_get_info(); + MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", + goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); + MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); + if (!connected) + { + /* (re)connect to the broker */ + if (connecting) + { + MySleep((1+opts.connectTimeout) * 1000); /* but wait for all pending connect attempts to timeout */ + } + else + { + rc = MQTTAsync_connect(mqttasyncContext, &opts); + if (rc != MQTTASYNC_SUCCESS) + { + failures++; + goto exit; + } + connecting = 1; + } + } + else + { + /* while connected send 100 message per second */ + int topicId; + for(topicId=0; topicId < 100; topicId++) + { + rc = test373SendPublishMessage(mqttasyncContext,topicId); + if (rc != MQTTASYNC_SUCCESS) break; + } + MySleep(1000); + } + } + MySleep(5000); + MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", + goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); + MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); + MQTTAsync_disconnect(mqttasyncContext, NULL); + MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", + goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); + MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); +exit: + MQTTAsync_destroy(&mqttasyncContext); + return failures; } void handleTrace(enum MQTTASYNC_TRACE_LEVELS level, char* message) @@ -149,7 +344,7 @@ int main(int argc, char** argv) { int* numtests = &tests; int rc = 0; - int (*tests[])() = { NULL, test_373}; + int (*tests[])() = { NULL, test_373}; sprintf(unique, "%u", rand()); MyLog(LOGA_INFO, "Random prefix/suffix is %s", unique); @@ -179,3 +374,9 @@ int main(int argc, char** argv) return rc; } + + +/* Local Variables: */ +/* indent-tabs-mode: t */ +/* c-basic-offset: 8 */ +/* End: */ From 2ceffbc7877c8a73a361d2296da8664da61f0691 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 4 Dec 2017 15:04:18 +0100 Subject: [PATCH 05/46] Moved the decrement of pendingMessageCnt to another call back function For some unknown reason, decrementing pendingMessageCnt in test373DeliveryComplete() does not work. Therefore moved to other call back functions. Signed-off-by: Juergen Kosel --- test/test_issue373.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/test_issue373.c b/test/test_issue373.c index 58900343..1bc29803 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -206,16 +206,17 @@ void test373ConnectionLost(void* context, char* cause) void test373DeliveryComplete(void* context, MQTTAsync_token token) { - pendingMessageCnt--; } void test373_onWriteSuccess(void* context, MQTTAsync_successData* response) { + pendingMessageCnt--; goodPublishCnt++; } void test373_onWriteFailure(void* context, MQTTAsync_failureData* response) { + pendingMessageCnt--; failedPublishCnt++; } From bed5c09a2567306f6d2f01cf6933af36dc6587dd Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 4 Dec 2017 15:04:58 +0100 Subject: [PATCH 06/46] Modified number of connect iterations and messages send per second Signed-off-by: Juergen Kosel --- test/test_issue373.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_issue373.c b/test/test_issue373.c index 1bc29803..d07014e0 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -286,7 +286,7 @@ int test_373(struct Options options) goto exit; } MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); - while (connectCnt < 10) + while (connectCnt < 5) { MyLog(LOGA_INFO, "Connected %d connectCnt %d\n",connected,connectCnt); mqtt_mem = Heap_get_info(); @@ -313,9 +313,9 @@ int test_373(struct Options options) } else { - /* while connected send 100 message per second */ + /* while connected send 1000 message per second */ int topicId; - for(topicId=0; topicId < 100; topicId++) + for(topicId=0; topicId < 1000; topicId++) { rc = test373SendPublishMessage(mqttasyncContext,topicId); if (rc != MQTTASYNC_SUCCESS) break; From 079247868663a80b6a3dd8f35152d56fba4ab49f Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 4 Dec 2017 15:43:58 +0100 Subject: [PATCH 07/46] Consider any not freed memory as test failure Signed-off-by: Juergen Kosel --- test/test_issue373.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/test_issue373.c b/test/test_issue373.c index d07014e0..d9e32ce0 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -326,11 +326,14 @@ int test_373(struct Options options) MySleep(5000); MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); + mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); MQTTAsync_disconnect(mqttasyncContext, NULL); + mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); + if (mqtt_mem->current_size > 0) failures++; /* consider any not freed memory as failure */ exit: MQTTAsync_destroy(&mqttasyncContext); return failures; From dfe4060157832695fadc1bff361b2c326e2954d9 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 4 Dec 2017 15:55:23 +0100 Subject: [PATCH 08/46] Fix Windows build of test_issue373 and increase number of iterations The functions implemented in Heap.c are not usable for Windows builds. Therefore use only for none MSVC builds. Increase the workload and number of connect/disconnects. Signed-off-by: Juergen Kosel --- test/test_issue373.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test/test_issue373.c b/test/test_issue373.c index d9e32ce0..e8482a7e 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -286,15 +286,17 @@ int test_373(struct Options options) goto exit; } MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); - while (connectCnt < 5) + while (connectCnt < 10) { - MyLog(LOGA_INFO, "Connected %d connectCnt %d\n",connected,connectCnt); - mqtt_mem = Heap_get_info(); - MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", - goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); - MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); if (!connected) { + MyLog(LOGA_INFO, "Connected %d connectCnt %d\n",connected,connectCnt); + MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", + goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); +#if !defined(_WINDOWS) + mqtt_mem = Heap_get_info(); + MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); +#endif /* (re)connect to the broker */ if (connecting) { @@ -320,20 +322,24 @@ int test_373(struct Options options) rc = test373SendPublishMessage(mqttasyncContext,topicId); if (rc != MQTTASYNC_SUCCESS) break; } - MySleep(1000); + MySleep(100); } } MySleep(5000); MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); +#if !defined(_WINDOWS) mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); +#endif MQTTAsync_disconnect(mqttasyncContext, NULL); - mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); +#if !defined(_WINDOWS) + mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); if (mqtt_mem->current_size > 0) failures++; /* consider any not freed memory as failure */ +#endif exit: MQTTAsync_destroy(&mqttasyncContext); return failures; From 2c3dc75e5c536dd9c1742054c204aea1c839bb87 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 4 Dec 2017 16:40:36 +0100 Subject: [PATCH 09/46] Move the evaluation of the not freed memory _after_ call of MQTTAsync_destroy() Signed-off-by: Juergen Kosel --- test/test_issue373.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/test_issue373.c b/test/test_issue373.c index e8482a7e..3bfb9e1c 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -338,10 +338,14 @@ int test_373(struct Options options) #if !defined(_WINDOWS) mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); - if (mqtt_mem->current_size > 0) failures++; /* consider any not freed memory as failure */ #endif exit: MQTTAsync_destroy(&mqttasyncContext); +#if !defined(_WINDOWS) + mqtt_mem = Heap_get_info(); + MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); + if (mqtt_mem->current_size > 0) failures++; /* consider any not freed memory as failure */ +#endif return failures; } From 2761fcea7eaaad5937da3a11d0e87c5a516540b1 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 5 Dec 2017 09:21:18 +0100 Subject: [PATCH 10/46] Reduce the tcp snd buffer to provocate issue #385 Signed-off-by: Juergen Kosel --- src/Socket.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Socket.c b/src/Socket.c index 939dbab9..73b1853c 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -679,6 +679,13 @@ int Socket_new(char* addr, int port, int* sock) if (setsockopt(*sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0) Log(LOG_ERROR, -1, "Could not set SO_NOSIGPIPE for socket %d", *sock); #endif +#if 1 + { + int optsend = 2 * 1440; + if (setsockopt(*sock, SOL_SOCKET, SO_SNDBUF, (void*)&optsend, sizeof(optsend)) != 0) + Log(LOG_ERROR, -1, "Could not set SO_SNDBUF for socket %d", *sock); + } +#endif Log(TRACE_MIN, -1, "New socket %d for %s, port %d", *sock, addr, port); if (Socket_addSocket(*sock) == SOCKET_ERROR) From d3c6d143834132e78bc38b43a8241beaa642c5bc Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 5 Dec 2017 09:35:10 +0100 Subject: [PATCH 11/46] Add trace output to verify that reducing the tcp send buffer forces TCPSOCKET_INTERRUPTED Signed-off-by: Juergen Kosel --- src/Socket.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Socket.c b/src/Socket.c index 73b1853c..c9629ad5 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -504,6 +504,12 @@ int Socket_putdatas(int socket, char* buf0, size_t buf0len, int count, char** bu } } exit: +#if 1 + if (rc == TCPSOCKET_INTERRUPTED) + { + Log(LOG_ERROR, -1, "Socket_putdatas: TCPSOCKET_INTERRUPTED"); + } +#endif FUNC_EXIT_RC(rc); return rc; } From 1f36a313ffbf30380617be4f298bbc15a60ac49b Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 5 Dec 2017 11:23:43 +0100 Subject: [PATCH 12/46] Add log output for failed message queueing in test due to disconnect Signed-off-by: Juergen Kosel --- test/test_issue373.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_issue373.c b/test/test_issue373.c index 3bfb9e1c..42513b45 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -247,6 +247,10 @@ int test373SendPublishMessage(MQTTAsync handle,int id) pendingMessageCnt++; if (pendingMessageCnt > pendingMessageCntMax) pendingMessageCntMax = pendingMessageCnt; } + else + { + MyLog(LOGA_INFO, "Failed to queue message for send with retvalue %d",rc); + } return rc; } From dff71726c89dce18c5efde3ad265449071acad0f Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 5 Dec 2017 16:38:59 +0100 Subject: [PATCH 13/46] Disable additional trace output Signed-off-by: Juergen Kosel --- src/Socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Socket.c b/src/Socket.c index 5a79ad7e..05ca34ab 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -532,7 +532,7 @@ int Socket_putdatas(int socket, char* buf0, size_t buf0len, int count, char** bu } } exit: -#if 1 +#if 0 if (rc == TCPSOCKET_INTERRUPTED) { Log(LOG_ERROR, -1, "Socket_putdatas: TCPSOCKET_INTERRUPTED"); From 4440ab7e68ce3db7087fb352da9ba74001079e01 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 5 Dec 2017 16:39:32 +0100 Subject: [PATCH 14/46] Increase connect / disconnect iterations Signed-off-by: Juergen Kosel --- test/test_issue373.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_issue373.c b/test/test_issue373.c index 42513b45..b0c98e8a 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -290,7 +290,7 @@ int test_373(struct Options options) goto exit; } MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); - while (connectCnt < 10) + while (connectCnt < 40) { if (!connected) { @@ -319,9 +319,9 @@ int test_373(struct Options options) } else { - /* while connected send 1000 message per second */ + /* while connected send 100 message per second */ int topicId; - for(topicId=0; topicId < 1000; topicId++) + for(topicId=0; topicId < 100; topicId++) { rc = test373SendPublishMessage(mqttasyncContext,topicId); if (rc != MQTTASYNC_SUCCESS) break; From e5daa54781cc1c9e8f6af403e121602d192a3c3d Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Wed, 22 Nov 2017 09:54:55 +0100 Subject: [PATCH 15/46] Allow to call free(NULL) as it is allowed by standard The function myfree() is used as a replacement for free(). Therefore it must not cause any failure, if someone calls myfree(NULL). Signed-off-by: Juergen Kosel --- src/Heap.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/Heap.c b/src/Heap.c index bef4c708..d382d6db 100644 --- a/src/Heap.c +++ b/src/Heap.c @@ -247,10 +247,13 @@ static int Internal_heap_unlink(char* file, int line, void* p) */ void myfree(char* file, int line, void* p) { - Thread_lock_mutex(heap_mutex); - if (Internal_heap_unlink(file, line, p)) - free(((int*)p)-1); - Thread_unlock_mutex(heap_mutex); + if (p) /* it is legal und usual to call free(NULL) */ + { + Thread_lock_mutex(heap_mutex); + if (Internal_heap_unlink(file, line, p)) + free(((int*)p)-1); + Thread_unlock_mutex(heap_mutex); + } } @@ -479,3 +482,8 @@ int main(int argc, char *argv[]) } #endif /* HEAP_UNIT_TESTS */ + +/* Local Variables: */ +/* indent-tabs-mode: t */ +/* c-basic-offset: 8 */ +/* End: */ From dccbcfc5f9fb18f45c4507f25f5a8470206c6314 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Wed, 6 Dec 2017 08:46:14 +0100 Subject: [PATCH 16/46] Report to trace if free(NULL) is called, which was not expected before Signed-off-by: Juergen Kosel --- src/Heap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Heap.c b/src/Heap.c index d382d6db..70468cea 100644 --- a/src/Heap.c +++ b/src/Heap.c @@ -254,6 +254,10 @@ void myfree(char* file, int line, void* p) free(((int*)p)-1); Thread_unlock_mutex(heap_mutex); } + else + { + Log(LOG_ERROR, -1, "Call of free(NULL) in %s,%d",file,line); + } } From b4bdb89861bb72537b8aa564db2d56b311b96803 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Wed, 6 Dec 2017 09:25:35 +0100 Subject: [PATCH 17/46] Set pointers to NULL after free Setting pointers to NULL after free never hurt, but may prevent double free and other problems. Signed-off-by: Juergen Kosel --- src/LinkedList.c | 6 ++++++ src/MQTTAsync.c | 7 +++++++ src/MQTTProtocolClient.c | 3 +++ src/SSLSocket.c | 3 +++ src/Socket.c | 6 ++++++ src/SocketBuffer.c | 1 + 6 files changed, 26 insertions(+) diff --git a/src/LinkedList.c b/src/LinkedList.c index a8d073ea..20f95149 100644 --- a/src/LinkedList.c +++ b/src/LinkedList.c @@ -218,7 +218,10 @@ static int ListUnlink(List* aList, void* content, int(*callback)(void*, void*), next = aList->current->next; if (freeContent) + { free(aList->current->content); + aList->current->content = NULL; + } if (saved == aList->current) saveddeleted = 1; free(aList->current); @@ -357,7 +360,10 @@ void ListEmpty(List* aList) { ListElement* first = aList->first; if (first->content != NULL) + { free(first->content); + first->content = NULL; + } aList->first = first->next; free(first); } diff --git a/src/MQTTAsync.c b/src/MQTTAsync.c index e5be6349..32902271 100644 --- a/src/MQTTAsync.c +++ b/src/MQTTAsync.c @@ -1008,8 +1008,10 @@ static void MQTTAsync_freeServerURIs(MQTTAsyncs* m) for (i = 0; i < m->serverURIcount; ++i) free(m->serverURIs[i]); + m->serverURIcount = 0; if (m->serverURIs) free(m->serverURIs); + m->serverURIs = NULL; } @@ -1023,7 +1025,9 @@ static void MQTTAsync_freeCommand1(MQTTAsync_queuedCommand *command) free(command->command.details.sub.topics[i]); free(command->command.details.sub.topics); + command->command.details.sub.topics = NULL; free(command->command.details.sub.qoss); + command->command.details.sub.qoss = NULL; } else if (command->command.type == UNSUBSCRIBE) { @@ -1033,13 +1037,16 @@ static void MQTTAsync_freeCommand1(MQTTAsync_queuedCommand *command) free(command->command.details.unsub.topics[i]); free(command->command.details.unsub.topics); + command->command.details.unsub.topics = NULL; } else if (command->command.type == PUBLISH) { /* qos 1 and 2 topics are freed in the protocol code when the flows are completed */ if (command->command.details.pub.destinationName) free(command->command.details.pub.destinationName); + command->command.details.pub.destinationName = NULL; free(command->command.details.pub.payload); + command->command.details.pub.payload = NULL; } } diff --git a/src/MQTTProtocolClient.c b/src/MQTTProtocolClient.c index fa3ff63c..90c6839f 100644 --- a/src/MQTTProtocolClient.c +++ b/src/MQTTProtocolClient.c @@ -668,11 +668,13 @@ void MQTTProtocol_freeClient(Clients* client) MQTTProtocol_freeMessageList(client->inboundMsgs); ListFree(client->messageQueue); free(client->clientID); + client->clientID = NULL; if (client->will) { free(client->will->payload); free(client->will->topic); free(client->will); + client->will = NULL; } #if defined(OPENSSL) if (client->sslopts) @@ -688,6 +690,7 @@ void MQTTProtocol_freeClient(Clients* client) if (client->sslopts->enabledCipherSuites) free((void*)client->sslopts->enabledCipherSuites); free(client->sslopts); + client->sslopts = NULL; } #endif /* don't free the client structure itself... this is done elsewhere */ diff --git a/src/SSLSocket.c b/src/SSLSocket.c index d17c8bcf..9deb09eb 100644 --- a/src/SSLSocket.c +++ b/src/SSLSocket.c @@ -855,7 +855,10 @@ int SSLSocket_putdatas(SSL* ssl, int socket, char* buf0, size_t buf0len, int cou for (i = 0; i < count; ++i) { if (frees[i]) + { free(buffers[i]); + buffers[i] = NULL; + } } } FUNC_EXIT_RC(rc); diff --git a/src/Socket.c b/src/Socket.c index 05ca34ab..83c87c47 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -818,7 +818,10 @@ int Socket_continueWrite(int socket) for (i = 0; i < pw->count; i++) { if (pw->frees[i]) + { free(pw->iovecs[i].iov_base); + pw->iovecs[i].iov_base = NULL; + } } rc = 1; /* signal complete */ Log(TRACE_MIN, -1, "ContinueWrite: partial write now complete for socket %d", socket); @@ -834,7 +837,10 @@ int Socket_continueWrite(int socket) for (i = 0; i < pw->count; i++) { if (pw->frees[i]) + { free(pw->iovecs[i].iov_base); + pw->iovecs[i].iov_base = NULL; + } } } #if defined(OPENSSL) diff --git a/src/SocketBuffer.c b/src/SocketBuffer.c index ba640f18..7cc51362 100644 --- a/src/SocketBuffer.c +++ b/src/SocketBuffer.c @@ -106,6 +106,7 @@ void SocketBuffer_freeDefQ(void) { free(def_queue->buf); free(def_queue); + def_queue = NULL; } From 6a2c1c48486220b1efdf1ea4fab38257149565af Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Thu, 7 Dec 2017 15:31:00 +0100 Subject: [PATCH 18/46] Build regression tests with enabled debug symbols Signed-off-by: Juergen Kosel --- travis-build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/travis-build.sh b/travis-build.sh index 5356f8ba..347486e8 100755 --- a/travis-build.sh +++ b/travis-build.sh @@ -6,7 +6,7 @@ rm -rf build.paho mkdir build.paho cd build.paho echo "travis build dir $TRAVIS_BUILD_DIR pwd $PWD" -cmake -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=FALSE -DPAHO_BUILD_SAMPLES=TRUE .. +cmake -DCMAKE_BUILD_TYPE=Debug -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=FALSE -DPAHO_BUILD_SAMPLES=TRUE .. make python ../test/mqttsas2.py & ctest -VV --timeout 600 From 779ca42a46afd3c80bd90a2bac68c8412b0dfc4b Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Fri, 8 Dec 2017 10:16:37 +0100 Subject: [PATCH 19/46] Protect call of Socket_noPendingWrites() with socket_mutex to fix issue #385 It turned out in https://github.com/eclipse/paho.mqtt.c/issues/385 that Socket_getReadySocket() could remove a list element, which is currently in use by a function called by Socket_noPendingWirte(). And this leads to memory corruption or segmentation fault. To fix this, this call of Socket_PendingWrites() in MQTTAsync.c needs to be protected by mutex_socket. Signed-off-by: Juergen Kosel --- src/MQTTAsync.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/MQTTAsync.c b/src/MQTTAsync.c index 32902271..3e79a89c 100644 --- a/src/MQTTAsync.c +++ b/src/MQTTAsync.c @@ -973,6 +973,17 @@ static void MQTTAsync_checkDisconnect(MQTTAsync handle, MQTTAsync_command* comma FUNC_EXIT; } +/** + * Call Socket_noPendingWrites(int socket) with protection by socket_mutex, see https://github.com/eclipse/paho.mqtt.c/issues/385 + */ +static int MQTTAsync_Socket_noPendingWrites(int socket) +{ + int rc; + Thread_lock_mutex(socket_mutex); + rc = Socket_noPendingWrites(socket); + Thread_unlock_mutex(socket_mutex); + return rc; +} /** * See if any pending writes have been completed, and cleanup if so. @@ -1154,7 +1165,7 @@ static int MQTTAsync_processCommand(void) continue; if (cmd->command.type == CONNECT || cmd->command.type == DISCONNECT || (cmd->client->c->connected && - cmd->client->c->connect_state == 0 && Socket_noPendingWrites(cmd->client->c->net.socket))) + cmd->client->c->connect_state == 0 && MQTTAsync_Socket_noPendingWrites(cmd->client->c->net.socket))) { if ((cmd->command.type == PUBLISH || cmd->command.type == SUBSCRIBE || cmd->command.type == UNSUBSCRIBE) && cmd->client->c->outboundMsgs->count >= MAX_MSG_ID - 1) From c69c82189e224d96d4966fabc9ae5f1e103e06a0 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Fri, 8 Dec 2017 10:53:23 +0100 Subject: [PATCH 20/46] Fix Windows build of test6 The functions implemented in Heap.c are not usable for Windows builds. Therefore use only for none MSVC builds. Signed-off-by: Juergen Kosel --- test/test6.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/test6.c b/test/test6.c index 327dc373..fc177814 100644 --- a/test/test6.c +++ b/test/test6.c @@ -510,10 +510,11 @@ int recreateReconnect(void) MyLog(LOGA_ALWAYS, "Recreating client"); MQTTAsync_destroy(&client); /* destroy the client object so that we force persistence to be read on recreate */ - +#if !defined(_WINDOWS) heap_info* mqtt_mem = 0; mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); +#endif //if (mqtt_mem->current_size > 20) // HeapScan(5); @@ -1028,12 +1029,12 @@ exit: destroy_exit: MQTTAsync_destroy(&control_client); -#include "Heap.h" +#if !defined(_WINDOWS) heap_info* mqtt_mem = 0; mqtt_mem = Heap_get_info(); MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); - if (mqtt_mem->current_size > 0) + /*if (mqtt_mem->current_size > 0) */ /*failures++*/; /* consider any not freed memory as failure */ - +#endif return 0; } From c48d9207987faa096279e649e00801c026b0071e Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Fri, 8 Dec 2017 10:36:55 +0100 Subject: [PATCH 21/46] Do not reduce the tcp send buffer size for production code Signed-off-by: Juergen Kosel --- src/Socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Socket.c b/src/Socket.c index c9629ad5..9e88cc04 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -685,7 +685,7 @@ int Socket_new(char* addr, int port, int* sock) if (setsockopt(*sock, SOL_SOCKET, SO_NOSIGPIPE, (void*)&opt, sizeof(opt)) != 0) Log(LOG_ERROR, -1, "Could not set SO_NOSIGPIPE for socket %d", *sock); #endif -#if 1 +#if defined(TESTING) { int optsend = 2 * 1440; if (setsockopt(*sock, SOL_SOCKET, SO_SNDBUF, (void*)&optsend, sizeof(optsend)) != 0) From 0c651aa2c9e7441d19876de5d7b7c153cc0220cd Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 5 Dec 2017 11:23:43 +0100 Subject: [PATCH 22/46] Add log output for failed message queueing in test due to disconnect Signed-off-by: Juergen Kosel --- test/test_issue373.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_issue373.c b/test/test_issue373.c index 3bfb9e1c..42513b45 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -247,6 +247,10 @@ int test373SendPublishMessage(MQTTAsync handle,int id) pendingMessageCnt++; if (pendingMessageCnt > pendingMessageCntMax) pendingMessageCntMax = pendingMessageCnt; } + else + { + MyLog(LOGA_INFO, "Failed to queue message for send with retvalue %d",rc); + } return rc; } From c9741998abb21be63c9628f1b7102b6e0f81f793 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Fri, 8 Dec 2017 13:58:22 +0100 Subject: [PATCH 23/46] Add helper script for test_issue373 to cyclically disconnect the VM running the broker Signed-off-by: Juergen Kosel --- test/python/controlVMnetworkstate.py | 74 ++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100755 test/python/controlVMnetworkstate.py diff --git a/test/python/controlVMnetworkstate.py b/test/python/controlVMnetworkstate.py new file mode 100755 index 00000000..29566b4c --- /dev/null +++ b/test/python/controlVMnetworkstate.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +import os +import sys +import time +import subprocess +import random +bindir='/usr/bin' +sys.path.append(bindir) + +def input_sel(prompt,max_,selectionoption): + # let the user choose the VM and verify selection + while True: + try: + print ('Please select from the list of running VMs\n\n'+'\n'.join(selectionoption)) + userin = int(raw_input(prompt)) + except ValueError: + print('\nThat was not a number\n\n') + continue + if userin > max_: + print('\nInput must be less than or equal to {0}.\n\n'.format(max_)) + elif userin < 1: + print('\nInput must be greater than or equal to 1\n\n') + else: + return userin + +def statustext(result): + if result == 0: + status = 'OK' + else: + status = 'Failed' + return status + +def controlvmnetworkstate(): + try: + offtime = 600 + ontime = 14 + vmdict={} + vmlist=[] + executable = os.path.join(bindir, 'VBoxManage') + + #retrieve a list of all running VMs + runningvms= subprocess.check_output('%s list runningvms' %executable,shell=True).splitlines() + if len(runningvms) != 0: + for n in range(0, len(runningvms)): + vmlist.append('%s: %s' %(n+1,runningvms[n].rsplit(' ',1)[0].strip('"'))) + vmdict[n+1]=runningvms[n].rsplit(' ',1)[-1] + usersel=input_sel('\nEnter the number of the VM: ',len(runningvms),vmlist) + + else: + print('Can not retrieve list of running VMs') + sys.exit() + + vmuuid=vmdict[usersel] + while True: + offtime = random.randint(60, 90) + ontime = random.randint(10, 90) + timenow = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) + on = subprocess.call('%s controlvm %s setlinkstate1 on' %(executable,vmuuid), + shell=True) + status=statustext(on) + print ('%s: Plug Network cable into VM %s for %ds: %s' % (timenow, runningvms[usersel-1].rsplit(' ',1)[0].strip('"'),ontime, str(status))) + time.sleep(ontime) + timenow = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime()) + off = subprocess.call('%s controlvm %s setlinkstate1 off' %(executable,vmuuid), + shell=True) + status = statustext(off) + print ('%s: Unplug Network cable from VM %s for %ds: %s' % (timenow, runningvms[usersel-1].rsplit(' ',1)[0].strip('"'),offtime, str(status))) + time.sleep(offtime) + except KeyboardInterrupt: + sys.exit('\nUser Interrupt') + except Exception as e: + print("Error in %s in function %s: %s" % (__name__, sys._getframe().f_code.co_name, e.message)) +if __name__ == "__main__": + sys.exit(controlvmnetworkstate()) From 00e3a0f56693a04cdcc3a580304fb942201cc0e8 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 5 Dec 2017 16:39:32 +0100 Subject: [PATCH 24/46] Extend test_issue373 to test also with QoS 1 and 2 Signed-off-by: Juergen Kosel --- test/test_issue373.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/test/test_issue373.c b/test/test_issue373.c index 42513b45..76eb4f5b 100644 --- a/test/test_issue373.c +++ b/test/test_issue373.c @@ -54,12 +54,16 @@ struct Options char* proxy_connection; /**< connection to proxy */ int verbose; int test_no; + unsigned int QoS; + unsigned int iterrations; } options = { "iot.eclipse.org:1883", "localhost:1883", 0, 0, + 0, + 5 }; void getopts(int argc, char** argv) @@ -227,7 +231,7 @@ int test373_messageArrived(void* context, char* topicName, int topicLen, MQTTAsy static char test373Payload[] = "No one is interested in this payload"; -int test373SendPublishMessage(MQTTAsync handle,int id) +int test373SendPublishMessage(MQTTAsync handle,int id, const unsigned int QoS) { int rc = 0; MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer; @@ -240,7 +244,7 @@ int test373SendPublishMessage(MQTTAsync handle,int id) pubmsg.payload = test373Payload; pubmsg.payloadlen = sizeof(test373Payload); - pubmsg.qos = 0; + pubmsg.qos = QoS; rc = MQTTAsync_sendMessage( handle, topic,&pubmsg,&opts); if (rc == MQTTASYNC_SUCCESS) { @@ -264,7 +268,9 @@ int test_373(struct Options options) char clientid[30 + sizeof(unique)]; heap_info* mqtt_mem = 0; + MyLog(LOGA_INFO, "Running test373 with QoS=%u, iterrations=%u\n",options.QoS,options.iterrations); sprintf(clientid, "paho-test373-%s", unique); + connectCnt = 0; rc = MQTTAsync_create(&mqttasyncContext, options.proxy_connection, clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL); @@ -290,7 +296,7 @@ int test_373(struct Options options) goto exit; } MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); - while (connectCnt < 10) + while (connectCnt < options.iterrations) { if (!connected) { @@ -319,11 +325,11 @@ int test_373(struct Options options) } else { - /* while connected send 1000 message per second */ + /* while connected send 100 message per second */ int topicId; - for(topicId=0; topicId < 1000; topicId++) + for(topicId=0; topicId < 100; topicId++) { - rc = test373SendPublishMessage(mqttasyncContext,topicId); + rc = test373SendPublishMessage(mqttasyncContext,topicId,options.QoS); if (rc != MQTTASYNC_SUCCESS) break; } MySleep(100); @@ -337,6 +343,7 @@ int test_373(struct Options options) MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); #endif MQTTAsync_disconnect(mqttasyncContext, NULL); + connected = 0; MyLog(LOGA_INFO, "PublishCnt %d, FailedCnt %d, Pending %d maxPending %d", goodPublishCnt,failedPublishCnt,pendingMessageCnt,pendingMessageCntMax); #if !defined(_WINDOWS) @@ -363,6 +370,7 @@ int main(int argc, char** argv) int* numtests = &tests; int rc = 0; int (*tests[])() = { NULL, test_373}; + unsigned int QoS; sprintf(unique, "%u", rand()); MyLog(LOGA_INFO, "Random prefix/suffix is %s", unique); @@ -374,9 +382,24 @@ int main(int argc, char** argv) { /* run all the tests */ for (options.test_no = 1; options.test_no < ARRAY_SIZE(tests); ++options.test_no) { - failures = 0; - MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); - rc += tests[options.test_no](options); /* return number of failures. 0 = test succeeded */ + /* test with QoS 0, 1 and 2 and just 5 iterrations */ + for (QoS = 0; QoS < 3; QoS++) + { + failures = 0; + options.QoS = QoS; + options.iterrations = 5; + MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); + rc += tests[options.test_no](options); /* return number of failures. 0 = test succeeded */ + } + if (rc == 0) + { + /* Test with much more iterrations for QoS = 0 */ + failures = 0; + options.QoS = 0; + options.iterrations = 100; + MQTTAsync_setTraceLevel(MQTTASYNC_TRACE_ERROR); + rc += tests[options.test_no](options); /* return number of failures. 0 = test succeeded */ + } } } else From 2d25517408e5b9aa53ca62a310011af0e4bf8261 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 12 Mar 2018 14:46:15 +0100 Subject: [PATCH 25/46] Lock the socket_mutex inside Socket_getReadySocket() To reduce the performance penalty of commit 779ca42a46afd3c80bd90a2bac68c8412b0dfc4b Ian has recommended to release the socket_mutex during the call of select. See https://github.com/eclipse/paho.mqtt.c/issues/385#issuecomment-372299490 As a preparation for this, the locking of the socket_mutex is moved inside the Socket_getReadySocket() function. Signed-off-by: Juergen Kosel --- src/MQTTAsync.c | 4 +--- src/MQTTClient.c | 4 +--- src/Socket.c | 4 +++- src/Socket.h | 3 ++- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/MQTTAsync.c b/src/MQTTAsync.c index 08faf585..e5f9a8aa 100644 --- a/src/MQTTAsync.c +++ b/src/MQTTAsync.c @@ -2967,10 +2967,8 @@ static MQTTPacket* MQTTAsync_cycle(int* sock, unsigned long timeout, int* rc) if ((*sock = SSLSocket_getPendingRead()) == -1) { #endif - Thread_lock_mutex(socket_mutex); /* 0 from getReadySocket indicates no work to do, -1 == error, but can happen normally */ - *sock = Socket_getReadySocket(0, &tp); - Thread_unlock_mutex(socket_mutex); + *sock = Socket_getReadySocket(0, &tp,socket_mutex); if (!tostop && *sock == 0 && (tp.tv_sec > 0L || tp.tv_usec > 0L)) MQTTAsync_sleep(100L); #if defined(OPENSSL) diff --git a/src/MQTTClient.c b/src/MQTTClient.c index ed446fc6..20e28f2e 100644 --- a/src/MQTTClient.c +++ b/src/MQTTClient.c @@ -1684,9 +1684,7 @@ static MQTTPacket* MQTTClient_cycle(int* sock, unsigned long timeout, int* rc) { /* 0 from getReadySocket indicates no work to do, -1 == error, but can happen normally */ #endif - Thread_lock_mutex(socket_mutex); - *sock = Socket_getReadySocket(0, &tp); - Thread_unlock_mutex(socket_mutex); + *sock = Socket_getReadySocket(0, &tp, socket_mutex); #if defined(OPENSSL) } #endif diff --git a/src/Socket.c b/src/Socket.c index f4f861a6..dc28575a 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -228,7 +228,7 @@ int isReady(int socket, fd_set* read_set, fd_set* write_set) * @param tp the timeout to be used for the select, unless overridden * @return the socket next ready, or 0 if none is ready */ -int Socket_getReadySocket(int more_work, struct timeval *tp) +int Socket_getReadySocket(int more_work, struct timeval *tp, mutex_type mutex) { int rc = 0; static struct timeval zero = {0L, 0L}; /* 0 seconds */ @@ -236,6 +236,7 @@ int Socket_getReadySocket(int more_work, struct timeval *tp) struct timeval timeout = one; FUNC_ENTRY; + Thread_lock_mutex(mutex); if (s.clientsds->count == 0) goto exit; @@ -301,6 +302,7 @@ int Socket_getReadySocket(int more_work, struct timeval *tp) ListNextElement(s.clientsds, &s.cur_clientsds); } exit: + Thread_unlock_mutex(mutex); FUNC_EXIT_RC(rc); return rc; } /* end getReadySocket */ diff --git a/src/Socket.h b/src/Socket.h index 1efe29ac..83a3f2ce 100644 --- a/src/Socket.h +++ b/src/Socket.h @@ -18,6 +18,7 @@ #if !defined(SOCKET_H) #define SOCKET_H +#include "Thread.h" /* Needed for mutex_type */ #include #if defined(WIN32) || defined(WIN64) @@ -124,7 +125,7 @@ typedef struct void Socket_outInitialize(void); void Socket_outTerminate(void); -int Socket_getReadySocket(int more_work, struct timeval *tp); +int Socket_getReadySocket(int more_work, struct timeval *tp,mutex_type mutex); int Socket_getch(int socket, char* c); char *Socket_getdata(int socket, size_t bytes, size_t* actual_len); int Socket_putdatas(int socket, char* buf0, size_t buf0len, int count, char** buffers, size_t* buflens, int* frees); From 341037269e00da935602c34c6aa4efe4d295e3bd Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 12 Mar 2018 14:56:45 +0100 Subject: [PATCH 26/46] Prevent release socket_mutex during call of select() As suggested in https://github.com/eclipse/paho.mqtt.c/issues/385#issuecomment-372299490 the socket_mutex is released during the call of select(), to avoid a performance penalty. Signed-off-by: Juergen Kosel --- src/Socket.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Socket.c b/src/Socket.c index dc28575a..b66c45b0 100644 --- a/src/Socket.c +++ b/src/Socket.c @@ -259,7 +259,11 @@ int Socket_getReadySocket(int more_work, struct timeval *tp, mutex_type mutex) memcpy((void*)&(s.rset), (void*)&(s.rset_saved), sizeof(s.rset)); memcpy((void*)&(pwset), (void*)&(s.pending_wset), sizeof(pwset)); - if ((rc = select(s.maxfdp1, &(s.rset), &pwset, NULL, &timeout)) == SOCKET_ERROR) + /* Prevent performance issue by unlocking the socket_mutex while waiting for a ready socket. */ + Thread_unlock_mutex(mutex); + rc = select(s.maxfdp1, &(s.rset), &pwset, NULL, &timeout); + Thread_lock_mutex(mutex); + if (rc == SOCKET_ERROR) { Socket_error("read select", 0); goto exit; From e858851455ebe00c96d0b1d50b725669e66eac49 Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Mon, 12 Mar 2018 16:49:27 +0100 Subject: [PATCH 27/46] Modify order of includes to fix travis build Signed-off-by: Juergen Kosel --- src/Socket.h | 3 ++- test/test6.c | 7 ------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/Socket.h b/src/Socket.h index 83a3f2ce..8b249aaf 100644 --- a/src/Socket.h +++ b/src/Socket.h @@ -18,7 +18,6 @@ #if !defined(SOCKET_H) #define SOCKET_H -#include "Thread.h" /* Needed for mutex_type */ #include #if defined(WIN32) || defined(WIN64) @@ -66,6 +65,8 @@ #define ULONG size_t #endif +#include "Thread.h" /* Needed for mutex_type */ + /** socket operation completed successfully */ #define TCPSOCKET_COMPLETE 0 #if !defined(SOCKET_ERROR) diff --git a/test/test6.c b/test/test6.c index 1871af3c..9c701287 100644 --- a/test/test6.c +++ b/test/test6.c @@ -1028,12 +1028,5 @@ exit: destroy_exit: MQTTAsync_destroy(&control_client); -#if !defined(_WINDOWS) - heap_info* mqtt_mem = 0; - mqtt_mem = Heap_get_info(); - MyLog(LOGA_INFO, "MQTT mem current %ld, max %ld",mqtt_mem->current_size,mqtt_mem->max_size); - /*if (mqtt_mem->current_size > 0) */ - /*failures++*/; /* consider any not freed memory as failure */ -#endif return 0; } From 231eda090d2a379c3767a58dfa6f08070378caee Mon Sep 17 00:00:00 2001 From: Juergen Kosel Date: Tue, 13 Mar 2018 08:37:24 +0100 Subject: [PATCH 28/46] Move definition of mutex_type into own header file To avoid inconsitstant definition of "bool", the definition of mutex_type is moved into its own header file. This way, Socket.h does not need to include Thread.h. Signed-off-by: Juergen Kosel --- src/Socket.h | 4 ++-- src/Thread.h | 4 ++-- src/mutex_type.h | 25 +++++++++++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 src/mutex_type.h diff --git a/src/Socket.h b/src/Socket.h index 8b249aaf..6add4196 100644 --- a/src/Socket.h +++ b/src/Socket.h @@ -65,7 +65,7 @@ #define ULONG size_t #endif -#include "Thread.h" /* Needed for mutex_type */ +#include "mutex_type.h" /* Needed for mutex_type */ /** socket operation completed successfully */ #define TCPSOCKET_COMPLETE 0 @@ -126,7 +126,7 @@ typedef struct void Socket_outInitialize(void); void Socket_outTerminate(void); -int Socket_getReadySocket(int more_work, struct timeval *tp,mutex_type mutex); +int Socket_getReadySocket(int more_work, struct timeval *tp, mutex_type mutex); int Socket_getch(int socket, char* c); char *Socket_getdata(int socket, size_t bytes, size_t* actual_len); int Socket_putdatas(int socket, char* buf0, size_t buf0len, int count, char** buffers, size_t* buflens, int* frees); diff --git a/src/Thread.h b/src/Thread.h index 995e221c..f61ca1d8 100644 --- a/src/Thread.h +++ b/src/Thread.h @@ -21,13 +21,14 @@ #if !defined(THREAD_H) #define THREAD_H +#include "mutex_type.h" /* Needed for mutex_type */ + #if defined(WIN32) || defined(WIN64) #include #define thread_type HANDLE #define thread_id_type DWORD #define thread_return_type DWORD #define thread_fn LPTHREAD_START_ROUTINE - #define mutex_type HANDLE #define cond_type HANDLE #define sem_type HANDLE #else @@ -37,7 +38,6 @@ #define thread_id_type pthread_t #define thread_return_type void* typedef thread_return_type (*thread_fn)(void*); - #define mutex_type pthread_mutex_t* typedef struct { pthread_cond_t cond; pthread_mutex_t mutex; } cond_type_struct; typedef cond_type_struct *cond_type; #if defined(OSX) diff --git a/src/mutex_type.h b/src/mutex_type.h new file mode 100644 index 00000000..97dd9985 --- /dev/null +++ b/src/mutex_type.h @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2009, 2014 IBM Corp. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Eclipse Distribution License v1.0 which accompany this distribution. + * + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Eclipse Distribution License is available at + * http://www.eclipse.org/org/documents/edl-v10.php. + * + *******************************************************************************/ +#ifndef _MUTEX_TYPE_H_ +#define _MUTEX_TYPE_H_ + +#if defined(WIN32) || defined(WIN64) + #include + #define mutex_type HANDLE +#else + #include + #define mutex_type pthread_mutex_t* +#endif + +#endif /* _MUTEX_TYPE_H_ */ From 10c895c5dafee4b9756da7a7df4e0b18eee56956 Mon Sep 17 00:00:00 2001 From: Ian Craggs Date: Sun, 25 Mar 2018 18:29:01 +0100 Subject: [PATCH 29/46] Fix copyright date --- src/mutex_type.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mutex_type.h b/src/mutex_type.h index 97dd9985..5760b370 100644 --- a/src/mutex_type.h +++ b/src/mutex_type.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2014 IBM Corp. + * Copyright (c) 2009, 2018 IBM Corp. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -11,7 +11,7 @@ * http://www.eclipse.org/org/documents/edl-v10.php. * *******************************************************************************/ -#ifndef _MUTEX_TYPE_H_ +#if !defined(_MUTEX_TYPE_H_) #define _MUTEX_TYPE_H_ #if defined(WIN32) || defined(WIN64) From c0a56c96bef5ec517287a967cdf5ee6add21ecc9 Mon Sep 17 00:00:00 2001 From: Ian Craggs Date: Tue, 3 Apr 2018 17:02:31 +0100 Subject: [PATCH 30/46] Fix for issue #285 --- src/MQTTPersistenceDefault.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/MQTTPersistenceDefault.c b/src/MQTTPersistenceDefault.c index 35c1f530..8d31a721 100644 --- a/src/MQTTPersistenceDefault.c +++ b/src/MQTTPersistenceDefault.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2016 IBM Corp. + * Copyright (c) 2009, 2018 IBM Corp. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -14,6 +14,7 @@ * Ian Craggs - initial API and implementation and/or initial documentation * Ian Craggs - async client updates * Ian Craggs - fix for bug 484496 + * Ian Craggs - fix for issue 285 *******************************************************************************/ /** @@ -86,15 +87,25 @@ int pstopen(void **handle, const char* clientID, const char* serverURI, void* co /* create clientDir directory */ /* pCrtDirName - holds the directory name we are currently trying to create. */ - /* This gets built up level by level until the full path name is created.*/ + /* This gets built up level by level untipwdl the full path name is created.*/ /* pTokDirName - holds the directory name that gets used by strtok. */ pCrtDirName = (char*)malloc( strlen(clientDir) + 1 ); pTokDirName = (char*)malloc( strlen(clientDir) + 1 ); strcpy( pTokDirName, clientDir ); - pToken = strtok_r( pTokDirName, "\\/", &save_ptr ); + /* If first character is directory separator, make sure it's in the created directory name #285 */ + if (*pTokDirName == '/' || *pTokDirName == '\\') + { + *pCrtDirName = *pTokDirName; + pToken = strtok_r( pTokDirName + 1, "\\/", &save_ptr ); + strcpy( pCrtDirName + 1, pToken ); + } + else + { + pToken = strtok_r( pTokDirName, "\\/", &save_ptr ); + strcpy( pCrtDirName, pToken ); + } - strcpy( pCrtDirName, pToken ); rc = pstmkdir( pCrtDirName ); pToken = strtok_r( NULL, "\\/", &save_ptr ); while ( (pToken != NULL) && (rc == 0) ) From 602f2d877840b0acfac755be003ee401c98d866b Mon Sep 17 00:00:00 2001 From: Ian Craggs Date: Thu, 5 Apr 2018 13:06:29 +0100 Subject: [PATCH 31/46] Update version numbers and use CMake packaging --- .travis.yml | 8 ++++++-- CMakeLists.txt | 11 ++++++++--- Makefile | 2 +- build.xml | 4 ++-- travis-build.sh | 1 + 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index f9c42291..4d126802 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,8 @@ env: # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # via the "travis encrypt" command using the project repo's public key - secure: "Ro53zVdGCjCQx9U4wvD9GBwB346tIQ7y1MWOAe1QrFWlmoQLC8KUeddQkc+27pdrOG9Fm9QQcI82EDlh0bfRBy1ITfWSVVZVfbNLv9sBWesND1F9YlnFpn/fag2OE+ULPSEJVJMxZoqiR9yiYWO3pTWue4YjCSuFAjpQNO6VnV3HiQJRG1jeaylx0QVLQWKAL/qkRbuqG9o4xpS1Kebaj86+q9UTHcL1a+Aj53u+Ajqnc9ZbUB/yBrfHyufTKpAD8Ef/FEIWXg2svtiWVEwEsPtdTn5P7AefJ2FNEyT4uMKIEBzWIPeWvUZLFF6U7QA07+uYDE0Ir4voPptBUlIYqQz1CUz9XCOPmM/N+GgqpyNyUjpMb4CM1b+iwBwcsHc0Z1JFcPz65ZMSt1D/WeUfQlaB/KxQBpz4lD2mxEmAuBIoGNrAG+FRULoY+xQSAf7V0W8am6QbHNnXif30mdkF3lgAhaAOwWO03JD7ctEJXqzRbMK8HrBkrgWfHsRRLFT50m8CrNLFz+3lCYuPHge2gHUMDfIHMxd4N9f2dlfV9GJkHQOQYwFfP5L2Y5Xq9KTnZX+bsglDC2WcOJu2F8h1LxTMV5Kku8zl1RZlEAt8Qa9EtCMczA3sL4NfGxazO22WpyOvHdwb26mhdJTgquI5oZsl71zcIf+WLGfgUAEq4/k=" - + - secure: "VQroIObZ3eCKl9+vDrzyZYxgNhELR7ToaYDW0989U7Mh77OBLcQyrveIhOidClE0uDggnThcBI6OACk6XrQvW+JrahjiQ4y9lBo+4Lu9MuaUKLUcGG+BNCC/Jgyskg8Gk3h+TEqFAtyzsdosQNbEvLAvPGwseiKiWQZUYVshLFCOZJxIp9SORQ73EWvbhTY0OL3GbUs9BZRo8w/TDcrr5ZgLEp3SKMOxCkv+pSpDpMNWiFin0IFB5cNMbS0bDRh6dyrHzJBJu7P2ZbCTm89rTtxL0mBmB1CcoOSXCHgbJ9Mjzx7OP7k4wsqwu4N8qVzUa52SwwNP0va8OL+Uw0+B8HRuOacPfv/t6vkbS5zBVq/nZUbcegcJm490nQstUIx4Psy+mdWCNwPf253fSuBpFR+B96ORRRz+tuJ8OQmInu7oKJe8yCW8h/yQL7xcv6e9SEMfqdXBHLkFQWomHrC1cOtIwZ69OY81cCwHj+36xx3s9iLBsz+niYLWD6gv+hAFc6zzzzrjuXayJ3gldsAJca2MzmT3E34mOOd3h52rFdnv4t73a/iy+RhWPy6ZOrEqsEY7E5Kxxr2msm0g5YVM1ZsavX1zSFHZ+J3dDelD5YpOR3u2rsPewAMjAxECRLLunRbCCOj9NRFhUR9KxWe2iTCgph4UOBw/OEgs7TXz6/I=" + - secure: "IugtAa0v5VLL22sUsvXAiGvYRKXwWsGYjaFeyk9fRqT82BVLI0wWMxJYKwIo43m1P1Vp+c7lmcNafjUWMJtrE/+gmhl6NPnF0yo3cUiR6pfDKIDDI7AXtuyhGJlsZhvmEz+SQvPLYlqWgAhQqXZio5lgqAtlUmsoToo5iL8HHUtjodR1z1sWKKjDssYI+bZlVAnXHMbUDJzRQeB5CdTDbbcKhRB0iEjCXBIa5YXUXuEcf2tc/bsvW4dvRDEtflKx58EPeCY2u2PJgRi5DlkPjHttszNZVRkC4JrVloSsE3im2fDbg2qAzmXSW64pre+OyyZU9LMh3tQBAozWUOEtqVI3O96M+yvGfJyroU0MyGiFf2sVVYLGJIOJUW1na/Lz0N+70ZLKoTpkOnvqrfybqtyZe7qmQznfWpVZFdGn0XPsYS6y3v1S3lWQlJO0vvkTvNoyFCmvJDx/F3EGl0RxVLfEZ889mzG985h0ZeciVrcDN/QAjqlFVmArQmalxfNe7yV0nOp2HkP3W0/dUpohqFixomhNHOcxN8rhkNEny9cCvsyQ8OyRlE9iK3t+ozxl8252NkbNqXYzN82GIuKtdqw+HHfDUnPUZWI5V9xS/6R7lqpan8Gc9jZh0t7W1xfkS4/b8f31JZDklVQe03SfU6/8kPUPgLMV89rZdJKDkvM=" script: - if [[ "$COVERITY_SCAN_BRANCH" != 1 ]]; then ./travis-build.sh; fi @@ -44,4 +45,7 @@ addons: - mosquitto - doxygen - +after_success: + - curl --ftp-create-dirs + -T *.tar.gz + sftp://${SFTP_USER}:${SFTP_PASSWORD}@build.eclipse.org/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ce36492..be8d2e86 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ #******************************************************************************* -# Copyright (c) 2015, 2017 logi.cals GmbH and others +# Copyright (c) 2015, 2018 logi.cals GmbH and others # # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 @@ -18,7 +18,7 @@ # Note: on OS X you should install XCode and the associated command-line tools CMAKE_MINIMUM_REQUIRED(VERSION 2.8.4) -PROJECT("paho" C) +PROJECT("Eclipse Paho C" C) MESSAGE(STATUS "CMake version: " ${CMAKE_VERSION}) MESSAGE(STATUS "CMake system name: " ${CMAKE_SYSTEM_NAME}) @@ -28,7 +28,7 @@ SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") ## build settings SET(PAHO_VERSION_MAJOR 1) SET(PAHO_VERSION_MINOR 2) -SET(PAHO_VERSION_PATCH 0) +SET(PAHO_VERSION_PATCH 1) SET(CLIENT_VERSION ${PAHO_VERSION_MAJOR}.${PAHO_VERSION_MINOR}.${PAHO_VERSION_PATCH}) INCLUDE(GNUInstallDirs) @@ -60,6 +60,11 @@ IF(PAHO_BUILD_DOCUMENTATION) ENDIF() ### packaging settings +SET(CPACK_PACKAGE_VENDOR "Eclipse Paho") +SET(CPACK_PACKAGE_NAME "Eclipse-Paho-MQTT-C") +INSTALL(FILES CONTRIBUTING.md epl-v10 edl-v10 README.md notice.html DESTINATION .) +FILE(GLOB samples "src/samples/*.c") +INSTALL(FILES ${samples} DESTINATION samples) IF (WIN32) SET(CPACK_GENERATOR "ZIP") ELSEIF(PAHO_BUILD_DEB_PACKAGE) diff --git a/Makefile b/Makefile index 3a73ac19..141382cb 100755 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ SHELL = /bin/sh .PHONY: clean, mkdir, install, uninstall, html ifndef release.version - release.version = 1.2.0 + release.version = 1.2.1 endif # determine current platform diff --git a/build.xml b/build.xml index 07a9ec38..da00fe1a 100644 --- a/build.xml +++ b/build.xml @@ -1,5 +1,5 @@