Fri 04 Sep 2009 02:38:06 AM UTC, original submission:
lwip application layer use tcpip_apimsg()[or other similar functions] send a message to tcpip thread. for example: netconn_XXX() usually call tcpip_apimsg() to execute do_XXX() function.
tcpip_apimsg() first call sys_mbox_post() send a message, and then wait tcpip thread execute this message. if user thread priority higher than tcpip thread, sys_mbox_post() do not make a scheduling. and then user thread wait a conn->op_completed semaphore block itself.
if before user thread call sys_mbox_post(), conn->op_completed semaphore already been signaled. user thread will not have any block. and tcpip_apimsg() will return immediately. but the message which tcpip_apimsg() send, is a LOCAL VARIABLE, the message must be damaged, and then tcpip thread fetch this message pointer. the message body is DEAD. Crash!
The above situation really happened! because not all conn->op_completed semaphore signals are activated by do_XXX() function. for example: net interface have a receive event, then tcpip thread are going to execute. if this packet is a tcp packet, then tcp_input() will be called. in tcp_input() function will call TCP_EVEN_SEND() or TCP_EVENT_RECV(). and then will call send_tcp() or poll_tcp(). then do_writemore() or do_close_internal() will be called. and then conn->op_completed semaphore will be signaled. if above case are happening in tcpip_apimsg() are going to send a message. Crash!
I tested using the two thread: one recv() and another send(), using one socket. these two thread priority higher than tcpip thread. use of large amounts of data test. and than crashed. When the system crashes, I see tcpip_apimsg() do not make any scheduling. in other words sys_mbox_post() and sys_arch_sem_wait() hasn't been blocked, conn->op_completed semaphore already been signaled.
but I using one thread first recv() and then send(), do not crash.
------------CODE-----------------
err_t
tcpip_apimsg(struct api_msg *apimsg)
{
struct tcpip_msg msg;
if (mbox != SYS_MBOX_NULL) {
msg.type = TCPIP_MSG_API;
msg.msg.apimsg = apimsg;
/////////////////////////////////////
// tcp_input() -> TCP_EVENT_SENT() -> (pcb)->sent() ->
// sent_tcp() -> do_writemore() -> sys_arch_sem_signal() !!!! error !!
/////////////////////////////////////
sys_mbox_post(mbox, &msg);
sys_arch_sem_wait(apimsg->msg.conn->op_completed, 0);
return ERR_OK;
}
return ERR_VAL;
}
---------------CODE-----------------------
|