@@ -619,19 +619,20 @@ static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg) {
619619 // we perform the AsyncClient teardown interlocked safely with the LwIP task.
620620
621621 // As a postcondition, the queue must not have any events referencing
622- // this AsyncClient. This is because it is possible for an error event
623- // to have been queued, clearing the pcb*, but after the async thread
624- // has committed to closing/destructing the AsyncClient object.
622+ // the AsyncClient in api_call_msg->close . This is because it is possible for
623+ // an error event to have been queued, clearing the pcb*, but after the async
624+ // thread has committed to closing/destructing the AsyncClient object.
625625
626626 tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
627627 msg->err = ERR_CONN ;
628628 if (*msg->pcb ) {
629629 tcp_pcb *pcb = *msg->pcb ;
630630 _reset_tcp_callbacks (pcb, msg->close );
631- msg-> err = tcp_close (pcb);
632- if (msg-> err != ERR_OK ) {
631+ if ( tcp_close (pcb) != ERR_OK ) {
632+ // We do not permit failure here: abandon the pcb anyways.
633633 tcp_abort (pcb);
634634 }
635+ msg->err = ERR_OK ;
635636 *msg->pcb = nullptr ; // PCB is now the property of LwIP
636637 } else {
637638 // Ensure there is not an error event queued for this client
@@ -641,9 +642,6 @@ static err_t _tcp_close_api(struct tcpip_api_call_data *api_call_msg) {
641642}
642643
643644static esp_err_t _tcp_close (tcp_pcb **pcb, AsyncClient *client) {
644- if (!pcb || !*pcb) {
645- return ERR_CONN ;
646- }
647645 tcp_api_call_t msg;
648646 msg.pcb = pcb;
649647 msg.close = client;
@@ -652,21 +650,29 @@ static esp_err_t _tcp_close(tcp_pcb **pcb, AsyncClient *client) {
652650}
653651
654652static err_t _tcp_abort_api (struct tcpip_api_call_data *api_call_msg) {
653+ // Like close(), we must ensure that the queue is cleared
655654 tcp_api_call_t *msg = (tcp_api_call_t *)api_call_msg;
656655 msg->err = ERR_CONN ;
657656 if (*msg->pcb ) {
658- tcp_abort (*msg->pcb );
657+ tcp_pcb *pcb = *msg->pcb ;
658+ _reset_tcp_callbacks (pcb, msg->close );
659+ tcp_abort (pcb);
659660 *msg->pcb = nullptr ; // PCB is now the property of LwIP
661+ msg->err = ERR_OK ;
662+ } else {
663+ // Ensure there is not an error event queued for this client
664+ _remove_events_for_client (msg->close );
660665 }
661666 return msg->err ;
662667}
663668
664- static esp_err_t _tcp_abort (tcp_pcb **pcb) {
669+ static esp_err_t _tcp_abort (tcp_pcb **pcb, AsyncClient *client ) {
665670 if (!pcb || !*pcb) {
666671 return ERR_CONN ;
667672 }
668673 tcp_api_call_t msg;
669674 msg.pcb = pcb;
675+ msg.close = client;
670676 tcpip_api_call (_tcp_abort_api, (struct tcpip_api_call_data *)&msg);
671677 return msg.err ;
672678}
@@ -912,7 +918,7 @@ void AsyncClient::close(bool now) {
912918
913919int8_t AsyncClient::abort () {
914920 if (_pcb) {
915- _tcp_abort (&_pcb);
921+ _tcp_abort (&_pcb, this );
916922 // _pcb is now NULL
917923 }
918924 return ERR_ABRT ;
@@ -977,13 +983,11 @@ void AsyncClient::ackPacket(struct pbuf *pb) {
977983
978984int8_t AsyncClient::_close () {
979985 // ets_printf("X: 0x%08x\n", (uint32_t)this);
980- int8_t err = ERR_OK ;
981- if (_pcb) {
982- _tcp_close (&_pcb, this );
983- // _pcb is now NULL
984- if (_discard_cb) {
985- _discard_cb (_discard_cb_arg, this );
986- }
986+ int8_t err = _tcp_close (&_pcb, this );
987+ // _pcb is now NULL
988+ if ((err == ERR_OK ) && _discard_cb) {
989+ // _pcb was closed here
990+ _discard_cb (_discard_cb_arg, this );
987991 }
988992 return err;
989993}
0 commit comments