mirror of
https://github.com/me-no-dev/AsyncTCP.git
synced 2025-08-02 20:24:42 +02:00
Merge pull request #64 from matt123p/fix-crash-on-fin
Fix crash caused by a race condition when the _lwip_fin function is called
This commit is contained in:
@@ -78,6 +78,7 @@ typedef struct {
|
|||||||
|
|
||||||
static xQueueHandle _async_queue;
|
static xQueueHandle _async_queue;
|
||||||
static TaskHandle_t _async_service_task_handle = NULL;
|
static TaskHandle_t _async_service_task_handle = NULL;
|
||||||
|
static tcp_pcb * pcb_recently_closed = NULL;
|
||||||
|
|
||||||
static inline bool _init_async_event_queue(){
|
static inline bool _init_async_event_queue(){
|
||||||
if(!_async_queue){
|
if(!_async_queue){
|
||||||
@@ -327,7 +328,6 @@ static int8_t _tcp_accept(void * arg, AsyncClient * client) {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
struct tcpip_api_call_data call;
|
struct tcpip_api_call_data call;
|
||||||
tcp_pcb * pcb;
|
tcp_pcb * pcb;
|
||||||
AsyncClient * client;
|
|
||||||
int8_t err;
|
int8_t err;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@@ -352,19 +352,19 @@ typedef struct {
|
|||||||
static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){
|
static err_t _tcp_output_api(struct tcpip_api_call_data *api_call_msg){
|
||||||
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
||||||
msg->err = ERR_CONN;
|
msg->err = ERR_CONN;
|
||||||
if(msg->client && msg->client->pcb() == msg->pcb){
|
if(msg->pcb != pcb_recently_closed) {
|
||||||
msg->err = tcp_output(msg->pcb);
|
msg->err = tcp_output(msg->pcb);
|
||||||
}
|
}
|
||||||
|
pcb_recently_closed = NULL;
|
||||||
return msg->err;
|
return msg->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _tcp_output(tcp_pcb * pcb, AsyncClient * client) {
|
static esp_err_t _tcp_output(tcp_pcb * pcb) {
|
||||||
if(!pcb){
|
if(!pcb){
|
||||||
return ERR_CONN;
|
return ERR_CONN;
|
||||||
}
|
}
|
||||||
tcp_api_call_t msg;
|
tcp_api_call_t msg;
|
||||||
msg.pcb = pcb;
|
msg.pcb = pcb;
|
||||||
msg.client = client;
|
|
||||||
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg);
|
tcpip_api_call(_tcp_output_api, (struct tcpip_api_call_data*)&msg);
|
||||||
return msg.err;
|
return msg.err;
|
||||||
}
|
}
|
||||||
@@ -372,19 +372,19 @@ static esp_err_t _tcp_output(tcp_pcb * pcb, AsyncClient * client) {
|
|||||||
static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){
|
static err_t _tcp_write_api(struct tcpip_api_call_data *api_call_msg){
|
||||||
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
||||||
msg->err = ERR_CONN;
|
msg->err = ERR_CONN;
|
||||||
if(msg->client && msg->client->pcb() == msg->pcb){
|
if(msg->pcb != pcb_recently_closed) {
|
||||||
msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags);
|
msg->err = tcp_write(msg->pcb, msg->write.data, msg->write.size, msg->write.apiflags);
|
||||||
}
|
}
|
||||||
|
pcb_recently_closed = NULL;
|
||||||
return msg->err;
|
return msg->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_t apiflags, AsyncClient * client) {
|
static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_t apiflags) {
|
||||||
if(!pcb){
|
if(!pcb){
|
||||||
return ERR_CONN;
|
return ERR_CONN;
|
||||||
}
|
}
|
||||||
tcp_api_call_t msg;
|
tcp_api_call_t msg;
|
||||||
msg.pcb = pcb;
|
msg.pcb = pcb;
|
||||||
msg.client = client;
|
|
||||||
msg.write.data = data;
|
msg.write.data = data;
|
||||||
msg.write.size = size;
|
msg.write.size = size;
|
||||||
msg.write.apiflags = apiflags;
|
msg.write.apiflags = apiflags;
|
||||||
@@ -395,20 +395,20 @@ static esp_err_t _tcp_write(tcp_pcb * pcb, const char* data, size_t size, uint8_
|
|||||||
static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){
|
static err_t _tcp_recved_api(struct tcpip_api_call_data *api_call_msg){
|
||||||
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
||||||
msg->err = ERR_CONN;
|
msg->err = ERR_CONN;
|
||||||
if(msg->client && msg->client->pcb() == msg->pcb){
|
if(msg->pcb != pcb_recently_closed) {
|
||||||
msg->err = 0;
|
msg->err = 0;
|
||||||
tcp_recved(msg->pcb, msg->received);
|
tcp_recved(msg->pcb, msg->received);
|
||||||
}
|
}
|
||||||
|
pcb_recently_closed = NULL;
|
||||||
return msg->err;
|
return msg->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len, AsyncClient * client) {
|
static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len) {
|
||||||
if(!pcb){
|
if(!pcb){
|
||||||
return ERR_CONN;
|
return ERR_CONN;
|
||||||
}
|
}
|
||||||
tcp_api_call_t msg;
|
tcp_api_call_t msg;
|
||||||
msg.pcb = pcb;
|
msg.pcb = pcb;
|
||||||
msg.client = client;
|
|
||||||
msg.received = len;
|
msg.received = len;
|
||||||
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg);
|
tcpip_api_call(_tcp_recved_api, (struct tcpip_api_call_data*)&msg);
|
||||||
return msg.err;
|
return msg.err;
|
||||||
@@ -417,19 +417,19 @@ static esp_err_t _tcp_recved(tcp_pcb * pcb, size_t len, AsyncClient * client) {
|
|||||||
static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){
|
static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg){
|
||||||
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
||||||
msg->err = ERR_CONN;
|
msg->err = ERR_CONN;
|
||||||
if(!msg->client || msg->client->pcb() == msg->pcb){
|
if(msg->pcb != pcb_recently_closed) {
|
||||||
msg->err = tcp_close(msg->pcb);
|
msg->err = tcp_close(msg->pcb);
|
||||||
}
|
}
|
||||||
|
pcb_recently_closed = NULL;
|
||||||
return msg->err;
|
return msg->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _tcp_close(tcp_pcb * pcb, AsyncClient * client) {
|
static esp_err_t _tcp_close(tcp_pcb * pcb) {
|
||||||
if(!pcb){
|
if(!pcb){
|
||||||
return ERR_CONN;
|
return ERR_CONN;
|
||||||
}
|
}
|
||||||
tcp_api_call_t msg;
|
tcp_api_call_t msg;
|
||||||
msg.pcb = pcb;
|
msg.pcb = pcb;
|
||||||
msg.client = client;
|
|
||||||
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg);
|
tcpip_api_call(_tcp_close_api, (struct tcpip_api_call_data*)&msg);
|
||||||
return msg.err;
|
return msg.err;
|
||||||
}
|
}
|
||||||
@@ -437,19 +437,19 @@ static esp_err_t _tcp_close(tcp_pcb * pcb, AsyncClient * client) {
|
|||||||
static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){
|
static err_t _tcp_abort_api(struct tcpip_api_call_data *api_call_msg){
|
||||||
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
tcp_api_call_t * msg = (tcp_api_call_t *)api_call_msg;
|
||||||
msg->err = ERR_CONN;
|
msg->err = ERR_CONN;
|
||||||
if(!msg->client || msg->client->pcb() == msg->pcb){
|
if(msg->pcb != pcb_recently_closed) {
|
||||||
tcp_abort(msg->pcb);
|
tcp_abort(msg->pcb);
|
||||||
}
|
}
|
||||||
|
pcb_recently_closed = NULL;
|
||||||
return msg->err;
|
return msg->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t _tcp_abort(tcp_pcb * pcb, AsyncClient * client) {
|
static esp_err_t _tcp_abort(tcp_pcb * pcb) {
|
||||||
if(!pcb){
|
if(!pcb){
|
||||||
return ERR_CONN;
|
return ERR_CONN;
|
||||||
}
|
}
|
||||||
tcp_api_call_t msg;
|
tcp_api_call_t msg;
|
||||||
msg.pcb = pcb;
|
msg.pcb = pcb;
|
||||||
msg.client = client;
|
|
||||||
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg);
|
tcpip_api_call(_tcp_abort_api, (struct tcpip_api_call_data*)&msg);
|
||||||
return msg.err;
|
return msg.err;
|
||||||
}
|
}
|
||||||
@@ -697,14 +697,14 @@ bool AsyncClient::connect(const char* host, uint16_t port){
|
|||||||
|
|
||||||
void AsyncClient::close(bool now){
|
void AsyncClient::close(bool now){
|
||||||
if(_pcb){
|
if(_pcb){
|
||||||
_tcp_recved(_pcb, _rx_ack_len, this);
|
_tcp_recved(_pcb, _rx_ack_len);
|
||||||
}
|
}
|
||||||
_close();
|
_close();
|
||||||
}
|
}
|
||||||
|
|
||||||
int8_t AsyncClient::abort(){
|
int8_t AsyncClient::abort(){
|
||||||
if(_pcb) {
|
if(_pcb) {
|
||||||
_tcp_abort(_pcb, this);
|
_tcp_abort(_pcb);
|
||||||
_pcb = NULL;
|
_pcb = NULL;
|
||||||
}
|
}
|
||||||
return ERR_ABRT;
|
return ERR_ABRT;
|
||||||
@@ -727,7 +727,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
|
|||||||
}
|
}
|
||||||
size_t will_send = (room < size) ? room : size;
|
size_t will_send = (room < size) ? room : size;
|
||||||
int8_t err = ERR_OK;
|
int8_t err = ERR_OK;
|
||||||
err = _tcp_write(_pcb, data, will_send, apiflags, this);
|
err = _tcp_write(_pcb, data, will_send, apiflags);
|
||||||
if(err != ERR_OK) {
|
if(err != ERR_OK) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -736,7 +736,7 @@ size_t AsyncClient::add(const char* data, size_t size, uint8_t apiflags) {
|
|||||||
|
|
||||||
bool AsyncClient::send(){
|
bool AsyncClient::send(){
|
||||||
int8_t err = ERR_OK;
|
int8_t err = ERR_OK;
|
||||||
err = _tcp_output(_pcb, this);
|
err = _tcp_output(_pcb);
|
||||||
if(err == ERR_OK){
|
if(err == ERR_OK){
|
||||||
_pcb_busy = true;
|
_pcb_busy = true;
|
||||||
_pcb_sent_at = millis();
|
_pcb_sent_at = millis();
|
||||||
@@ -749,7 +749,7 @@ size_t AsyncClient::ack(size_t len){
|
|||||||
if(len > _rx_ack_len)
|
if(len > _rx_ack_len)
|
||||||
len = _rx_ack_len;
|
len = _rx_ack_len;
|
||||||
if(len){
|
if(len){
|
||||||
_tcp_recved(_pcb, len, this);
|
_tcp_recved(_pcb, len);
|
||||||
}
|
}
|
||||||
_rx_ack_len -= len;
|
_rx_ack_len -= len;
|
||||||
return len;
|
return len;
|
||||||
@@ -759,7 +759,7 @@ void AsyncClient::ackPacket(struct pbuf * pb){
|
|||||||
if(!pb){
|
if(!pb){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_tcp_recved(_pcb, pb->len, this);
|
_tcp_recved(_pcb, pb->len);
|
||||||
pbuf_free(pb);
|
pbuf_free(pb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -778,7 +778,7 @@ int8_t AsyncClient::_close(){
|
|||||||
tcp_err(_pcb, NULL);
|
tcp_err(_pcb, NULL);
|
||||||
tcp_poll(_pcb, NULL, 0);
|
tcp_poll(_pcb, NULL, 0);
|
||||||
_tcp_clear_events(this);
|
_tcp_clear_events(this);
|
||||||
err = _tcp_close(_pcb, this);
|
err = _tcp_close(_pcb);
|
||||||
if(err != ERR_OK) {
|
if(err != ERR_OK) {
|
||||||
err = abort();
|
err = abort();
|
||||||
}
|
}
|
||||||
@@ -840,6 +840,7 @@ int8_t AsyncClient::_lwip_fin(tcp_pcb* pcb, int8_t err) {
|
|||||||
if(tcp_close(_pcb) != ERR_OK) {
|
if(tcp_close(_pcb) != ERR_OK) {
|
||||||
tcp_abort(_pcb);
|
tcp_abort(_pcb);
|
||||||
}
|
}
|
||||||
|
pcb_recently_closed = _pcb;
|
||||||
_pcb = NULL;
|
_pcb = NULL;
|
||||||
return ERR_OK;
|
return ERR_OK;
|
||||||
}
|
}
|
||||||
@@ -880,7 +881,7 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
|
|||||||
if(!_ack_pcb) {
|
if(!_ack_pcb) {
|
||||||
_rx_ack_len += b->len;
|
_rx_ack_len += b->len;
|
||||||
} else if(_pcb) {
|
} else if(_pcb) {
|
||||||
_tcp_recved(_pcb, b->len, this);
|
_tcp_recved(_pcb, b->len);
|
||||||
}
|
}
|
||||||
pbuf_free(b);
|
pbuf_free(b);
|
||||||
}
|
}
|
||||||
@@ -1227,7 +1228,7 @@ void AsyncServer::begin(){
|
|||||||
err = _tcp_bind(_pcb, &local_addr, _port);
|
err = _tcp_bind(_pcb, &local_addr, _port);
|
||||||
|
|
||||||
if (err != ERR_OK) {
|
if (err != ERR_OK) {
|
||||||
_tcp_close(_pcb, NULL);
|
_tcp_close(_pcb);
|
||||||
log_e("bind error: %d", err);
|
log_e("bind error: %d", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1246,7 +1247,7 @@ void AsyncServer::end(){
|
|||||||
if(_pcb){
|
if(_pcb){
|
||||||
tcp_arg(_pcb, NULL);
|
tcp_arg(_pcb, NULL);
|
||||||
tcp_accept(_pcb, NULL);
|
tcp_accept(_pcb, NULL);
|
||||||
_tcp_abort(_pcb, NULL);
|
_tcp_abort(_pcb);
|
||||||
_pcb = NULL;
|
_pcb = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user