22
22
* Ian Craggs - MQTT 3.1.1 support
23
23
* Rong Xiang, Ian Craggs - C++ compatibility
24
24
* Ian Craggs - fix for bug 442400: reconnecting after network cable unplugged
25
+ * Ian Craggs - fix for bug 444934 - incorrect free in freeCommand1
26
+ * Ian Craggs - fix for bug 445891 - assigning msgid is not thread safe
25
27
*******************************************************************************/
26
28
27
29
/**
@@ -75,6 +77,8 @@ enum MQTTAsync_threadStates
75
77
76
78
enum MQTTAsync_threadStates sendThread_state = STOPPED ;
77
79
enum MQTTAsync_threadStates receiveThread_state = STOPPED ;
80
+ static thread_id_type sendThread_id = 0 ,
81
+ receiveThread_id = 0 ;
78
82
79
83
#if defined(WIN32 ) || defined(WIN64 )
80
84
static mutex_type mqttasync_mutex = NULL ;
@@ -325,15 +329,15 @@ void MQTTAsync_lock_mutex(mutex_type amutex)
325
329
{
326
330
int rc = Thread_lock_mutex (amutex );
327
331
if (rc != 0 )
328
- Log (LOG_ERROR , 0 , "Error %d locking mutex" , rc );
332
+ Log (LOG_ERROR , 0 , "Error %s locking mutex" , strerror ( rc ) );
329
333
}
330
334
331
335
332
336
void MQTTAsync_unlock_mutex (mutex_type amutex )
333
337
{
334
338
int rc = Thread_unlock_mutex (amutex );
335
339
if (rc != 0 )
336
- Log (LOG_ERROR , 0 , "Error %d unlocking mutex" , rc );
340
+ Log (LOG_ERROR , 0 , "Error %s unlocking mutex" , strerror ( rc ) );
337
341
}
338
342
339
343
@@ -840,21 +844,19 @@ void MQTTAsync_freeCommand1(MQTTAsync_queuedCommand *command)
840
844
int i ;
841
845
842
846
for (i = 0 ; i < command -> command .details .sub .count ; i ++ )
843
- {
844
847
free (command -> command .details .sub .topics [i ]);
845
- free ( command -> command . details . sub . topics );
846
- free (command -> command .details .sub .qoss );
847
- }
848
+
849
+ free (command -> command .details .sub .topics );
850
+ free ( command -> command . details . sub . qoss );
848
851
}
849
852
else if (command -> command .type == UNSUBSCRIBE )
850
853
{
851
854
int i ;
852
855
853
856
for (i = 0 ; i < command -> command .details .unsub .count ; i ++ )
854
- {
855
857
free (command -> command .details .unsub .topics [i ]);
856
- free ( command -> command . details . unsub . topics );
857
- }
858
+
859
+ free ( command -> command . details . unsub . topics );
858
860
}
859
861
else if (command -> command .type == PUBLISH )
860
862
{
@@ -1255,6 +1257,7 @@ thread_return_type WINAPI MQTTAsync_sendThread(void* n)
1255
1257
FUNC_ENTRY ;
1256
1258
MQTTAsync_lock_mutex (mqttasync_mutex );
1257
1259
sendThread_state = RUNNING ;
1260
+ sendThread_id = Thread_getid ();
1258
1261
MQTTAsync_unlock_mutex (mqttasync_mutex );
1259
1262
while (!tostop )
1260
1263
{
@@ -1281,6 +1284,7 @@ thread_return_type WINAPI MQTTAsync_sendThread(void* n)
1281
1284
sendThread_state = STOPPING ;
1282
1285
MQTTAsync_lock_mutex (mqttasync_mutex );
1283
1286
sendThread_state = STOPPED ;
1287
+ sendThread_id = 0 ;
1284
1288
MQTTAsync_unlock_mutex (mqttasync_mutex );
1285
1289
FUNC_EXIT ;
1286
1290
return 0 ;
@@ -1455,6 +1459,7 @@ thread_return_type WINAPI MQTTAsync_receiveThread(void* n)
1455
1459
FUNC_ENTRY ;
1456
1460
MQTTAsync_lock_mutex (mqttasync_mutex );
1457
1461
receiveThread_state = RUNNING ;
1462
+ receiveThread_id = Thread_getid ();
1458
1463
while (!tostop )
1459
1464
{
1460
1465
int rc = SOCKET_ERROR ;
@@ -1671,6 +1676,7 @@ thread_return_type WINAPI MQTTAsync_receiveThread(void* n)
1671
1676
}
1672
1677
}
1673
1678
receiveThread_state = STOPPED ;
1679
+ receiveThread_id = 0 ;
1674
1680
MQTTAsync_unlock_mutex (mqttasync_mutex );
1675
1681
#if !defined(WIN32 ) && !defined(WIN64 )
1676
1682
if (sendThread_state != STOPPED )
@@ -2143,6 +2149,56 @@ int MQTTAsync_isConnected(MQTTAsync handle)
2143
2149
}
2144
2150
2145
2151
2152
+ int cmdMessageIDCompare (void * a , void * b )
2153
+ {
2154
+ MQTTAsync_queuedCommand * cmd = (MQTTAsync_queuedCommand * )a ;
2155
+ return cmd -> command .token == * (int * )b ;
2156
+ }
2157
+
2158
+
2159
+ /**
2160
+ * Assign a new message id for a client. Make sure it isn't already being used and does
2161
+ * not exceed the maximum.
2162
+ * @param m a client structure
2163
+ * @return the next message id to use, or 0 if none available
2164
+ */
2165
+ int MQTTAsync_assignMsgId (MQTTAsyncs * m )
2166
+ {
2167
+ int start_msgid = m -> c -> msgID ;
2168
+ int msgid = start_msgid ;
2169
+ thread_id_type thread_id = 0 ;
2170
+ int locked = 0 ;
2171
+
2172
+ /* need to check: commands list and response list for a client */
2173
+ FUNC_ENTRY ;
2174
+ /* We might be called in a callback. In which case, this mutex will be already locked. */
2175
+ thread_id = Thread_getid ();
2176
+ if (thread_id != sendThread_id && thread_id != receiveThread_id )
2177
+ {
2178
+ MQTTAsync_lock_mutex (mqttasync_mutex );
2179
+ locked = 1 ;
2180
+ }
2181
+
2182
+ msgid = (msgid == MAX_MSG_ID ) ? 1 : msgid + 1 ;
2183
+ while (ListFindItem (commands , & msgid , cmdMessageIDCompare ) ||
2184
+ ListFindItem (m -> responses , & msgid , cmdMessageIDCompare ))
2185
+ {
2186
+ msgid = (msgid == MAX_MSG_ID ) ? 1 : msgid + 1 ;
2187
+ if (msgid == start_msgid )
2188
+ { /* we've tried them all - none free */
2189
+ msgid = 0 ;
2190
+ break ;
2191
+ }
2192
+ }
2193
+ if (msgid != 0 )
2194
+ m -> c -> msgID = msgid ;
2195
+ if (locked )
2196
+ MQTTAsync_unlock_mutex (mqttasync_mutex );
2197
+ FUNC_EXIT_RC (msgid );
2198
+ return msgid ;
2199
+ }
2200
+
2201
+
2146
2202
int MQTTAsync_subscribeMany (MQTTAsync handle , int count , char * const * topic , int * qos , MQTTAsync_responseOptions * response )
2147
2203
{
2148
2204
MQTTAsyncs * m = handle ;
@@ -2175,7 +2231,7 @@ int MQTTAsync_subscribeMany(MQTTAsync handle, int count, char* const* topic, int
2175
2231
goto exit ;
2176
2232
}
2177
2233
}
2178
- if ((msgid = MQTTProtocol_assignMsgId ( m -> c )) == 0 )
2234
+ if ((msgid = MQTTAsync_assignMsgId ( m )) == 0 )
2179
2235
{
2180
2236
rc = MQTTASYNC_NO_MORE_MSGIDS ;
2181
2237
goto exit ;
@@ -2248,7 +2304,7 @@ int MQTTAsync_unsubscribeMany(MQTTAsync handle, int count, char* const* topic, M
2248
2304
goto exit ;
2249
2305
}
2250
2306
}
2251
- if ((msgid = MQTTProtocol_assignMsgId ( m -> c )) == 0 )
2307
+ if ((msgid = MQTTAsync_assignMsgId ( m )) == 0 )
2252
2308
{
2253
2309
rc = MQTTASYNC_NO_MORE_MSGIDS ;
2254
2310
goto exit ;
@@ -2307,7 +2363,7 @@ int MQTTAsync_send(MQTTAsync handle, const char* destinationName, int payloadlen
2307
2363
rc = MQTTASYNC_BAD_UTF8_STRING ;
2308
2364
else if (qos < 0 || qos > 2 )
2309
2365
rc = MQTTASYNC_BAD_QOS ;
2310
- else if (qos > 0 && (msgid = MQTTProtocol_assignMsgId ( m -> c )) == 0 )
2366
+ else if (qos > 0 && (msgid = MQTTAsync_assignMsgId ( m )) == 0 )
2311
2367
rc = MQTTASYNC_NO_MORE_MSGIDS ;
2312
2368
2313
2369
if (rc != MQTTASYNC_SUCCESS )
0 commit comments