Skip to content

Commit e8b824e

Browse files
committed
fix(lwip): Fix lwip multi-thread issue
internal: e7c378b6
1 parent d941ccb commit e8b824e

File tree

4 files changed

+126
-18
lines changed

4 files changed

+126
-18
lines changed

VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ gwen:
1313
gitlab:
1414
espconn: 3a998034
1515
freertos: ac047746
16-
lwip: 3c4f800b
16+
lwip: 829319d2
1717
driver: 7bee5263
1818
mbedtls: 1ac9f1f4
1919
ssl: eefb383a

lib/liblwip.a

2.71 KB
Binary file not shown.

third_party/lwip/api/api_msg.c

+5
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,10 @@ poll_tcp(void *arg, struct tcp_pcb *pcb)
295295
lwip_netconn_do_writemore(conn);
296296
} else if (conn->state == NETCONN_CLOSE) {
297297
lwip_netconn_do_close_internal(conn);
298+
} else if (conn->state == NETCONN_NONE) {
299+
return ERR_OK;
298300
}
301+
299302
/* @todo: implement connect timeout here? */
300303

301304
/* Did a nonblocking write fail before? Then check available write-space. */
@@ -331,6 +334,8 @@ sent_tcp(void *arg, struct tcp_pcb *pcb, u16_t len)
331334
lwip_netconn_do_writemore(conn);
332335
} else if (conn->state == NETCONN_CLOSE) {
333336
lwip_netconn_do_close_internal(conn);
337+
} else if (conn->state == NETCONN_NONE) {
338+
return ERR_OK;
334339
}
335340

336341
if (conn) {

third_party/lwip/api/multi-threads/sockets_mt.c

+120-17
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,65 @@ typedef struct _sock_mt sock_mt_t;
6666
#define SOCK_MT_DEBUG(level, ...)
6767
#endif
6868

69+
#if 0
6970
#define SOCK_MT_LOCK(s, l) \
7071
{ \
7172
SOCK_MT_DEBUG(1, "s %d l %d enter ", s, l); \
7273
sys_mutex_lock(&sockets_mt[s].lock[l]); \
7374
SOCK_MT_DEBUG(1, "OK\n"); \
7475
}
7576

77+
#define SOCK_MT_LOCK_RET(s, l, r) \
78+
{ \
79+
SOCK_MT_LOCK(s, l); \
80+
r = ERR_OK; \
81+
}
82+
#else
83+
#define SOCK_MT_LOCK(s, l) \
84+
{ \
85+
SOCK_MT_DEBUG(1, "s %d l %d enter ", s, l); \
86+
while (1) { \
87+
err_t err; \
88+
SYS_ARCH_DECL_PROTECT(lev); \
89+
\
90+
SYS_ARCH_PROTECT(lev); \
91+
if (sockets_mt[s].lock[l]) \
92+
err = sys_mutex_trylock(&sockets_mt[s].lock[l]); \
93+
else \
94+
err = ERR_VAL; \
95+
SYS_ARCH_UNPROTECT(lev); \
96+
\
97+
if (err == ERR_OK) \
98+
break; \
99+
else if (err == ERR_VAL) \
100+
return -1; \
101+
\
102+
vTaskDelay(1); \
103+
} \
104+
SOCK_MT_DEBUG(1, "OK\n"); \
105+
}
106+
107+
#define SOCK_MT_LOCK_RET(s, l, r) \
108+
{ \
109+
SOCK_MT_DEBUG(1, "s %d l %d enter ", s, l); \
110+
while (1) { \
111+
SYS_ARCH_DECL_PROTECT(lev); \
112+
\
113+
SYS_ARCH_PROTECT(lev); \
114+
if (sockets_mt[s].lock[l]) \
115+
r = sys_mutex_trylock(&sockets_mt[s].lock[l]); \
116+
else \
117+
r = ERR_VAL; \
118+
SYS_ARCH_UNPROTECT(lev); \
119+
\
120+
if (r == ERR_OK || ERR_VAL) \
121+
break; \
122+
vTaskDelay(1); \
123+
} \
124+
SOCK_MT_DEBUG(1, "OK\n"); \
125+
}
126+
#endif
127+
76128
#define SOCK_MT_TRYLOCK(s, l, r) \
77129
{ \
78130
SOCK_MT_DEBUG(1, "s %d l %d try enter ", s, l); \
@@ -257,17 +309,21 @@ LOCAL int lwip_enter_mt_select(int s, int arg)
257309
goto failed1;
258310

259311
if (FD_ISSET(i, read_set)) {
312+
err_t err;
313+
260314
SOCK_MT_SET_READ_SEL(i);
261-
SOCK_MT_LOCK(i, SOCK_MT_RECV_LOCK);
262-
if (SOCK_MT_GET_SHUTDOWN(i) != SOCK_MT_SHUTDOWN_NONE) {
315+
SOCK_MT_LOCK_RET(i, SOCK_MT_RECV_LOCK, err);
316+
if (err != ERR_OK || SOCK_MT_GET_SHUTDOWN(i) != SOCK_MT_SHUTDOWN_NONE) {
263317
goto failed2;
264318
}
265319
}
266320

267321
if (FD_ISSET(i, write_set)) {
322+
err_t err;
323+
268324
SOCK_MT_SET_WRITE_SEL(i);
269-
SOCK_MT_LOCK(i, SOCK_MT_STATE_LOCK);
270-
if (SOCK_MT_GET_SHUTDOWN(i) != SOCK_MT_SHUTDOWN_NONE) {
325+
SOCK_MT_LOCK_RET(i, SOCK_MT_STATE_LOCK, err);
326+
if (err != ERR_OK || SOCK_MT_GET_SHUTDOWN(i) != SOCK_MT_SHUTDOWN_NONE) {
271327
goto failed3;
272328
}
273329
}
@@ -408,6 +464,43 @@ LOCAL const ICACHE_RODATA_ATTR STORE_ATTR lwip_io_mt_fn lwip_exit_mt_table[] = {
408464
lwip_exit_mt_close
409465
};
410466

467+
LOCAL void lwip_do_sync_send(void *arg)
468+
{
469+
struct netconn *conn = arg;
470+
471+
SYS_ARCH_DECL_PROTECT(lev);
472+
SYS_ARCH_PROTECT(lev);
473+
if (conn->current_msg) {
474+
conn->current_msg->err = ERR_OK;
475+
conn->current_msg = NULL;
476+
}
477+
conn->state = NETCONN_NONE;
478+
SYS_ARCH_UNPROTECT(lev);
479+
if (sys_sem_valid(&(conn->snd_op_completed)))
480+
sys_sem_signal(&(conn->snd_op_completed));
481+
482+
/*
483+
* if we use "op_completed" for its sync semaphore, then socket functions
484+
* which are blocked by op_completed will be waked up.
485+
*
486+
* So we had better use a specific semaphore for the function, ioctrl_completed
487+
* may be a good choise.
488+
*/
489+
sys_sem_signal(&(conn->ioctrl_completed));
490+
}
491+
492+
LOCAL void lwip_do_sync_rst_state(void *arg)
493+
{
494+
struct netconn *conn = arg;
495+
496+
SYS_ARCH_DECL_PROTECT(lev);
497+
SYS_ARCH_PROTECT(lev);
498+
conn->state = NETCONN_NONE;
499+
SYS_ARCH_UNPROTECT(lev);
500+
501+
sys_sem_signal(&(conn->ioctrl_completed));
502+
}
503+
411504
LOCAL void lwip_sync_state_mt(struct lwip_sock *sock , int state)
412505
{
413506
SOCK_MT_DEBUG(1, "sync state %d\n", state);
@@ -419,16 +512,8 @@ LOCAL void lwip_sync_state_mt(struct lwip_sock *sock , int state)
419512
break;
420513
case SOCK_MT_STATE_SEND :
421514
{
422-
SYS_ARCH_DECL_PROTECT(lev);
423-
SYS_ARCH_PROTECT(lev);
424-
if (sock->conn->current_msg) {
425-
sock->conn->current_msg->err = ERR_OK;
426-
sock->conn->current_msg = NULL;
427-
}
428-
sock->conn->state = NETCONN_NONE;
429-
SYS_ARCH_UNPROTECT(lev);
430-
if (sys_sem_valid(&(sock->conn->snd_op_completed)))
431-
sys_sem_signal(&(sock->conn->snd_op_completed));
515+
tcpip_callback(lwip_do_sync_send, sock->conn);
516+
sys_arch_sem_wait(&sock->conn->ioctrl_completed, 0);
432517
break;
433518
}
434519
case SOCK_MT_STATE_CONNECT :
@@ -458,15 +543,19 @@ LOCAL void lwip_sync_mt(int s)
458543
{
459544
int module = 0;
460545
int ret;
546+
struct lwip_sock *sock;
461547

462548
while (module < SOCK_MT_SELECT) {
463549
extern void sys_arch_msleep(int ms);
464550
int ret;
465-
struct lwip_sock *sock;
466551

467552
SOCK_MT_TRYLOCK(s, module, ret);
468553
if (ret == ERR_OK) {
469-
SOCK_MT_UNLOCK(s, module);
554+
/*
555+
* we always lock the mutex in case of other thread entering,
556+
* other thread will be blocked at "SOCK_MT_LOCK" and poll-check
557+
*/
558+
//SOCK_MT_UNLOCK(s, module);
470559
module++;
471560
continue;
472561
}
@@ -494,6 +583,12 @@ LOCAL void lwip_sync_mt(int s)
494583

495584
sys_arch_msleep(LWIP_SYNC_MT_SLEEP_MS);
496585
}
586+
587+
sock = tryget_socket(s);
588+
if (sock) {
589+
tcpip_callback(lwip_do_sync_rst_state, sock->conn);
590+
sys_arch_sem_wait(&sock->conn->ioctrl_completed, 0);
591+
}
497592
}
498593

499594
int lwip_socket_mt(int domain, int type, int protocol)
@@ -764,6 +859,8 @@ int lwip_close_mt(int s)
764859
{
765860
int ret;
766861
int i;
862+
SYS_ARCH_DECL_PROTECT(lev);
863+
sys_mutex_t lock_tmp[SOCK_MT_LOCK_MAX];
767864

768865
lwip_shutdown_mt(s, SHUT_RDWR);
769866

@@ -773,10 +870,16 @@ int lwip_close_mt(int s)
773870

774871
LWIP_EXIT_MT(s, SOCK_MT_CLOSE, 0);
775872

873+
SYS_ARCH_PROTECT(lev);
776874
for (i = 0 ; i < SOCK_MT_LOCK_MAX; i++) {
777-
sys_mutex_free(&sockets_mt[s].lock[i]);
875+
lock_tmp[i] = sockets_mt[s].lock[i];
778876
sockets_mt[s].lock[i] = NULL;
779877
}
878+
SYS_ARCH_UNPROTECT(lev);
879+
880+
for (i = 0 ; i < SOCK_MT_LOCK_MAX; i++) {
881+
sys_mutex_free(&lock_tmp[i]);
882+
}
780883

781884
return ret;
782885
}

0 commit comments

Comments
 (0)