How to propertly close listener socket in TCP server
Posted: Fri Mar 11, 2022 2:16 pm
I got a little problem with propertly closing listener socket. I tried two methods:
1. First was just calling shutdown + close (but sometimes it isn't escaping socket accept function)
2. Second was forcing close by using SO_LINGER (but sometimes it's thow an error)
assertion "don't call tcp_abort/tcp_abandon for listen-pcbs" failed: file "C:/msys32/home/Dell/esp/esp-at/esp-idf/components/lwip/lwip/src/core/tcp.c", line 577, function: tcp_abandon
abort() was called at PC 0x402ae154 on core 0
The main reason is to close propertly socket or whole task.
My TCP_SERVICE_TASK
TCP_STOP_FUNCTION
1. First was just calling shutdown + close (but sometimes it isn't escaping socket accept function)
2. Second was forcing close by using SO_LINGER (but sometimes it's thow an error)
assertion "don't call tcp_abort/tcp_abandon for listen-pcbs" failed: file "C:/msys32/home/Dell/esp/esp-at/esp-idf/components/lwip/lwip/src/core/tcp.c", line 577, function: tcp_abandon
abort() was called at PC 0x402ae154 on core 0
The main reason is to close propertly socket or whole task.
My TCP_SERVICE_TASK
Code: Select all
static void tcp_server_task(void *pvParameters)
{
char addr_str[128];
int addr_family;
int ip_protocol;
STOP_TCP_TASK = 0;
while (1)
{
if (STOP_TCP_TASK == 1) break;
#ifdef CONFIG_EXAMPLE_IPV4
struct sockaddr_in destAddr;
destAddr.sin_addr.s_addr = htonl(INADDR_ANY);
destAddr.sin_family = AF_INET;
destAddr.sin_port = htons(TCP_PORT);
addr_family = AF_INET;
ip_protocol = IPPROTO_IP;
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
#else // IPV6
struct sockaddr_in6 destAddr;
bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un));
destAddr.sin6_family = AF_INET6;
destAddr.sin6_port = htons(TCP_PORT);
addr_family = AF_INET6;
ip_protocol = IPPROTO_IPV6;
inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
#endif
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < 0)
{
KOSA_LOG(TAG, "Unable to create socket: errno %d", errno);
break;
}
KOSA_LOG(TAG, "Socket created");
if (STOP_TCP_TASK == 1)
{
break;
}
int on = 1;
int err = setsockopt (listen_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on));
KOSA_LOG(TAG, "Socket setsockopt err= %d", err);
err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
KOSA_LOG(TAG, "Socket binded err= %d", err);
if (err != 0)
{
KOSA_LOG(TAG, "Socket unable to bind: errno %d", errno);
break;
}
if (STOP_TCP_TASK == 1)
{
break;
}
err = listen(listen_sock, 1);
if (err != 0)
{
KOSA_LOG(TAG, "Error occured during listen: errno %d", errno);
break;
}
LISTEN_SOCKET = listen_sock;
if (STOP_TCP_TASK == 1)
{
break;
}
while (1)
{ //listen loop
KOSA_LOG(TAG, "Socket listening");
struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
uint addrLen = sizeof(sourceAddr);
int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
if (sock < 0)
{
KOSA_LOG(TAG, "Unable to accept connection: errno %d", errno);
break;
} else
{
listen_loop(sock);
}
if (STOP_TCP_TASK == 1) break;
}
shutdown(listen_sock, 0);
close(listen_sock);
// jeĹĽli jest to rozmyslne przerwanie suchania to konczÄ™ caly watek TCP
if (STOP_TCP_TASK == 1) break;
}
KOSA_LOG(TAG, "kosa_tcp_server_task END");
STOP_TCP_TASK = 0;
TCP_STATE = TCP_NOTHING; //TCP is already close
xSemaphoreGive(tcp_del_sem);
vTaskDelete(NULL);
}
Code: Select all
static void tcp_stop_code(void)
{
if (TCP_STATE == TCP_NOTHING) //TCP_STATE
{
KOSA_LOG(TAG,"Already stopped");
}
else
{
tcp_del_sem = xSemaphoreCreateBinary();
KOSA_LOG(TAG,"Linger start");
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
if (PEER_CONNECTED == 0)
{
STOP_TCP_TASK = 1;
if (TCP_STATE == TCP_SERVER)
{
if (setsockopt(LISTEN_SOCKET, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == 0) {
KOSA_LOG(TAG,"Linger ok");
if (LISTEN_SOCKET != -1) close(LISTEN_SOCKET);
}
//if (shutdown(LISTEN_SOCKET, 0)) KOSA_LOG(TAG,"Cannot shutdown LISTEN_SOCKET");
//if (shutdown(LISTEN_SOCKET, 0)) KOSA_LOG(TAG,"Cannot shutdown LISTEN_SOCKET");
//if (close(LISTEN_SOCKET)) KOSA_LOG(TAG,"Cannot close LISTEN_SOCKET");
}
else
{
if (setsockopt(TCP_CLIENT_SOCK, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == 0) {
KOSA_LOG(TAG,"Linger ok");
if (TCP_CLIENT_SOCK != -1) close(TCP_CLIENT_SOCK);
}
// if (shutdown(TCP_CLIENT_SOCK, 0)) KOSA_LOG(TAG,"Cannot shutdown CLIENT_SOCKET");
// if (close(TCP_CLIENT_SOCK)) KOSA_LOG(TAG,"Cannot close CLIENT_SOCKET");
}
}
else
{
STOP_TCP_TASK = 1;
//if (shutdown(SEND_SOCKET, SHUT_RDWR)) KOSA_LOG(TAG,"Cannot shoutdown SEND_SOCKET");
if (setsockopt(SEND_SOCKET, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) == 0) {
KOSA_LOG(TAG,"Linger ok");
if (SEND_SOCKET != -1) close(SEND_SOCKET);
}
}
KOSA_LOG(TAG,"Waiting for semaphore");
BaseType_t err = xSemaphoreTake(tcp_del_sem, portMAX_DELAY);
KOSA_LOG(TAG,"semaphore err - %d",err);
// KOSA_LOG(TAG,"Juz zastopowane");
vSemaphoreDelete(tcp_del_sem);
}
KOSA_LOG(TAG, "kosa_tcp_stop!");
}