diff --git a/src/AsyncTCP.cpp b/src/AsyncTCP.cpp index 8b4bc16..d433c0c 100644 --- a/src/AsyncTCP.cpp +++ b/src/AsyncTCP.cpp @@ -39,6 +39,26 @@ extern "C"{ #include #endif +#define TAG "AsyncTCP" + +// https://github.com/espressif/arduino-esp32/issues/10526 +#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING +#define TCP_MUTEX_LOCK() \ + if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + ESP_LOGE(TAG, "LOCK_TCPIP_CORE @ %s:%d", __FILE__, __LINE__); \ + LOCK_TCPIP_CORE(); \ + } + +#define TCP_MUTEX_UNLOCK() \ + if (sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) { \ + ESP_LOGE(TAG, "UNLOCK_TCPIP_CORE @ %s:%d", __FILE__, __LINE__); \ + UNLOCK_TCPIP_CORE(); \ + } +#else // CONFIG_LWIP_TCPIP_CORE_LOCKING +#define TCP_MUTEX_LOCK() +#define TCP_MUTEX_UNLOCK() +#endif // CONFIG_LWIP_TCPIP_CORE_LOCKING + #define INVALID_CLOSED_SLOT -1 /* @@ -600,11 +620,13 @@ AsyncClient::AsyncClient(tcp_pcb* pcb) _closed_slot = INVALID_CLOSED_SLOT; if(_pcb){ _rx_last_packet = millis(); + TCP_MUTEX_LOCK(); tcp_arg(_pcb, this); tcp_recv(_pcb, &_tcp_recv); tcp_sent(_pcb, &_tcp_sent); tcp_err(_pcb, &_tcp_error); tcp_poll(_pcb, &_tcp_poll, 1); + TCP_MUTEX_UNLOCK(); if(!_allocate_closed_slot()) { _close(); } @@ -631,11 +653,13 @@ AsyncClient& AsyncClient::operator=(const AsyncClient& other){ _closed_slot = other._closed_slot; if (_pcb) { _rx_last_packet = millis(); + TCP_MUTEX_LOCK(); tcp_arg(_pcb, this); tcp_recv(_pcb, &_tcp_recv); tcp_sent(_pcb, &_tcp_sent); tcp_err(_pcb, &_tcp_error); tcp_poll(_pcb, &_tcp_poll, 1); + TCP_MUTEX_UNLOCK(); } return *this; } @@ -722,8 +746,10 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ return false; } + TCP_MUTEX_LOCK(); tcp_pcb* pcb = tcp_new_ip_type(addr.type); if (!pcb){ + TCP_MUTEX_UNLOCK(); log_e("pcb == NULL"); return false; } @@ -733,6 +759,7 @@ bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){ tcp_recv(pcb, &_tcp_recv); tcp_sent(pcb, &_tcp_sent); tcp_poll(pcb, &_tcp_poll, 1); + TCP_MUTEX_UNLOCK(); esp_err_t err =_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected); return err == ESP_OK; } @@ -863,11 +890,13 @@ int8_t AsyncClient::_close(){ //ets_printf("X: 0x%08x\n", (uint32_t)this); int8_t err = ERR_OK; if(_pcb) { + TCP_MUTEX_LOCK(); tcp_arg(_pcb, NULL); tcp_sent(_pcb, NULL); tcp_recv(_pcb, NULL); tcp_err(_pcb, NULL); tcp_poll(_pcb, NULL, 0); + TCP_MUTEX_UNLOCK(); _tcp_clear_events(this); err = _tcp_close(_pcb, _closed_slot); if(err != ERR_OK) { @@ -928,6 +957,7 @@ int8_t AsyncClient::_connected(tcp_pcb* pcb, int8_t err){ void AsyncClient::_error(int8_t err) { if(_pcb){ + TCP_MUTEX_LOCK(); tcp_arg(_pcb, NULL); if(_pcb->state == LISTEN) { tcp_sent(_pcb, NULL); @@ -935,6 +965,7 @@ void AsyncClient::_error(int8_t err) { tcp_err(_pcb, NULL); tcp_poll(_pcb, NULL, 0); } + TCP_MUTEX_UNLOCK(); _free_closed_slot(); _pcb = NULL; } @@ -952,6 +983,7 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { log_d("0x%08x != 0x%08x", (uint32_t)pcb, (uint32_t)_pcb); return ERR_OK; } + TCP_MUTEX_LOCK(); tcp_arg(_pcb, NULL); if(_pcb->state == LISTEN) { tcp_sent(_pcb, NULL); @@ -959,6 +991,7 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) { tcp_err(_pcb, NULL); tcp_poll(_pcb, NULL, 0); } + TCP_MUTEX_UNLOCK(); if(tcp_close(_pcb) != ERR_OK) { tcp_abort(_pcb); } @@ -1461,7 +1494,9 @@ void AsyncServer::begin(){ return; } int8_t err; + TCP_MUTEX_LOCK(); _pcb = tcp_new_ip_type(_bind4 && _bind6 ? IPADDR_TYPE_ANY : (_bind6 ? IPADDR_TYPE_V6 : IPADDR_TYPE_V4)); + TCP_MUTEX_UNLOCK(); if (!_pcb){ log_e("_pcb == NULL"); return; @@ -1493,14 +1528,18 @@ void AsyncServer::begin(){ log_e("listen_pcb == NULL"); return; } + TCP_MUTEX_LOCK(); tcp_arg(_pcb, (void*) this); tcp_accept(_pcb, &_s_accept); + TCP_MUTEX_UNLOCK(); } void AsyncServer::end(){ if(_pcb){ + TCP_MUTEX_LOCK(); tcp_arg(_pcb, NULL); tcp_accept(_pcb, NULL); + TCP_MUTEX_UNLOCK(); if(tcp_close(_pcb) != ERR_OK){ _tcp_abort(_pcb, -1); }