@@ -333,7 +333,7 @@ AsyncWebSocketClient::AsyncWebSocketClient(AsyncWebServerRequest *request, Async
333
333
AsyncWebSocketClient::~AsyncWebSocketClient () {
334
334
{
335
335
#ifdef ESP32
336
- std::lock_guard<std::mutex > lock (_lock);
336
+ std::lock_guard<std::recursive_mutex > lock (_lock);
337
337
#endif
338
338
_messageQueue.clear ();
339
339
_controlQueue.clear ();
@@ -351,7 +351,7 @@ void AsyncWebSocketClient::_onAck(size_t len, uint32_t time) {
351
351
_lastMessageTime = millis ();
352
352
353
353
#ifdef ESP32
354
- std::lock_guard <std::mutex > lock (_lock);
354
+ std::unique_lock <std::recursive_mutex > lock (_lock);
355
355
#endif
356
356
357
357
if (!_controlQueue.empty ()) {
@@ -362,6 +362,14 @@ void AsyncWebSocketClient::_onAck(size_t len, uint32_t time) {
362
362
_controlQueue.pop_front ();
363
363
_status = WS_DISCONNECTED;
364
364
if (_client) {
365
+ #ifdef ESP32
366
+ /*
367
+ Unlocking has to be called before return execution otherwise std::unique_lock ::~unique_lock() will get an exception pthread_mutex_unlock.
368
+ Due to _client->close(true) shall call the callback function _onDisconnect()
369
+ The calling flow _onDisconnect() --> _handleDisconnect() --> ~AsyncWebSocketClient()
370
+ */
371
+ lock.unlock ();
372
+ #endif
365
373
_client->close (true );
366
374
}
367
375
return ;
@@ -385,7 +393,7 @@ void AsyncWebSocketClient::_onPoll() {
385
393
}
386
394
387
395
#ifdef ESP32
388
- std::unique_lock<std::mutex > lock (_lock);
396
+ std::unique_lock<std::recursive_mutex > lock (_lock);
389
397
#endif
390
398
if (_client && _client->canSend () && (!_controlQueue.empty () || !_messageQueue.empty ())) {
391
399
_runQueue ();
@@ -415,21 +423,21 @@ void AsyncWebSocketClient::_runQueue() {
415
423
416
424
bool AsyncWebSocketClient::queueIsFull () const {
417
425
#ifdef ESP32
418
- std::lock_guard<std::mutex > lock (_lock);
426
+ std::lock_guard<std::recursive_mutex > lock (_lock);
419
427
#endif
420
428
return (_messageQueue.size () >= WS_MAX_QUEUED_MESSAGES) || (_status != WS_CONNECTED);
421
429
}
422
430
423
431
size_t AsyncWebSocketClient::queueLen () const {
424
432
#ifdef ESP32
425
- std::lock_guard<std::mutex > lock (_lock);
433
+ std::lock_guard<std::recursive_mutex > lock (_lock);
426
434
#endif
427
435
return _messageQueue.size ();
428
436
}
429
437
430
438
bool AsyncWebSocketClient::canSend () const {
431
439
#ifdef ESP32
432
- std::lock_guard<std::mutex > lock (_lock);
440
+ std::lock_guard<std::recursive_mutex > lock (_lock);
433
441
#endif
434
442
return _messageQueue.size () < WS_MAX_QUEUED_MESSAGES;
435
443
}
@@ -440,7 +448,7 @@ bool AsyncWebSocketClient::_queueControl(uint8_t opcode, const uint8_t *data, si
440
448
}
441
449
442
450
#ifdef ESP32
443
- std::lock_guard<std::mutex > lock (_lock);
451
+ std::lock_guard<std::recursive_mutex > lock (_lock);
444
452
#endif
445
453
446
454
_controlQueue.emplace_back (opcode, data, len, mask);
@@ -458,14 +466,22 @@ bool AsyncWebSocketClient::_queueMessage(AsyncWebSocketSharedBuffer buffer, uint
458
466
}
459
467
460
468
#ifdef ESP32
461
- std::lock_guard <std::mutex > lock (_lock);
469
+ std::unique_lock <std::recursive_mutex > lock (_lock);
462
470
#endif
463
471
464
472
if (_messageQueue.size () >= WS_MAX_QUEUED_MESSAGES) {
465
473
if (closeWhenFull) {
466
474
_status = WS_DISCONNECTED;
467
475
468
476
if (_client) {
477
+ #ifdef ESP32
478
+ /*
479
+ Unlocking has to be called before return execution otherwise std::unique_lock ::~unique_lock() will get an exception pthread_mutex_unlock.
480
+ Due to _client->close(true) shall call the callback function _onDisconnect()
481
+ The calling flow _onDisconnect() --> _handleDisconnect() --> ~AsyncWebSocketClient()
482
+ */
483
+ lock.unlock ();
484
+ #endif
469
485
_client->close (true );
470
486
}
471
487
@@ -551,6 +567,7 @@ void AsyncWebSocketClient::_onTimeout(uint32_t time) {
551
567
void AsyncWebSocketClient::_onDisconnect () {
552
568
// Serial.println("onDis");
553
569
_client = nullptr ;
570
+ _server->_handleDisconnect (this );
554
571
}
555
572
556
573
void AsyncWebSocketClient::_onData (void *pbuf, size_t plen) {
@@ -857,6 +874,16 @@ AsyncWebSocketClient *AsyncWebSocket::_newClient(AsyncWebServerRequest *request)
857
874
return &_clients.back ();
858
875
}
859
876
877
+ void AsyncWebSocket::_handleDisconnect (AsyncWebSocketClient *client) {
878
+ const auto client_id = client->id ();
879
+ const auto iter = std::find_if (std::begin (_clients), std::end (_clients), [client_id](const AsyncWebSocketClient &c) {
880
+ return c.id () == client_id;
881
+ });
882
+ if (iter != std::end (_clients)) {
883
+ _clients.erase (iter);
884
+ }
885
+ }
886
+
860
887
bool AsyncWebSocket::availableForWriteAll () {
861
888
return std::none_of (std::begin (_clients), std::end (_clients), [](const AsyncWebSocketClient &c) {
862
889
return c.queueIsFull ();
0 commit comments