[lwip-users] Nonblocking sockets problem

768 views
Skip to first unread message

Åke Forslund

unread,
Mar 12, 2012, 1:13:34 PM3/12/12
to lwip-...@nongnu.org

Hello,

 

we’ve run into a bit of a problem when we switched from blocking sockets to non-blocking sockets. From what we can tell when lwip_recvfrom() is executed it always return EWOULDBLOCK  because sock->rcvevent is never incremented and thus

 

if (((flags & MSG_DONTWAIT) || netconn_is_nonblocking(sock->conn)) &&

          (sock->rcvevent <= 0))

 

is always true. We added some debug-prints in the case NETCONN_EVT_RCVPLUS in event_callback() showing that  rcvevent was only incremented when the socket was set as blocking.

 

I’m having trouble seeing where to probe for the error so if anyone has an idea of where to look, I would be very thankful. Is there any options in lwipopt that could trigger this behavior?

From where is event_callback() triggered normally, it’s added as a callback to the netconnection-object but where is this callback called?

We’re running Lwip 1.40.

 

Best regards

/Åke Forslund

 

 

Åke Forslund

Embedded software engineer

Product Development

NIBE

Tfn: +46 (0)433 273296

 

Simon Goldschmidt

unread,
Mar 13, 2012, 4:06:22 AM3/13/12
to Mailing list for lwIP users
"Åke Forslund" <Ake.Fo...@nibe.se> wrote:
> We added some debug-prints in the case NETCONN_EVT_RCVPLUS
> in event_callback() showing that rcvevent was only incremented when the
> socket was set as blocking.
>
> I'm having trouble seeing where to probe for the error so if anyone has an
> idea of where to look, I would be very thankful. Is there any options in
> lwipopt that could trigger this behavior?
> From where is event_callback() triggered normally, it's added as a
> callback to the netconnection-object but where is this callback called?

The callback is called via the macro API_EVENT(), which is mainly called with RECVPLUS from the raw API recv- and accept-callbacks in api_msg.c (those are called from tcpip_thread). However, it is also called with RECVMINUS from netconn_recv_data() in api_lib.c (called from your application thread).

Which type of socket are you using (tcp, udp, raw)?

Could you provide a simple test code that reproduces this, that would make it much easier for me to check.

Thanks,
Simon
--
NEU: FreePhone 3-fach-Flat mit kostenlosem Smartphone!
Jetzt informieren: http://mobile.1und1.de/?ac=OM.PW.PW003K20328T7073a

_______________________________________________
lwip-users mailing list
lwip-...@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users

Åke Forslund

unread,
Mar 14, 2012, 4:19:28 AM3/14/12
to Mailing list for lwIP users
Hi again, this is not the original code but a implementation of the problem in our simple telnet-server for debug. Code below. In our original code we use ioctlsocket() to set non-blocking but using lwip_ fcntl() makes no difference.

void task_telnet(void * arg)
{
int lSocketRecv;
u32_t lAddrSize;
struct addrinfo *sListenAddr, hints;
char buffer[1024];
unsigned short u16L_buffPtr = 0;
int nbytes;
unsigned char one = 1;

LWIP_DEBUGF(SOCKETS_DEBUG, ("Recv Task started!\n"));
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;

lwip_getaddrinfo("0.0.0.0", "23", &hints, &sListenAddr);

lSocketRecv = lwip_socket(sListenAddr->ai_family, sListenAddr->ai_socktype, sListenAddr->ai_protocol);


lwip_bind(lSocketRecv, sListenAddr->ai_addr, sListenAddr->ai_addrlen);
//ioctlsocket(lSocketRecv, FIONBIO, &one);
lwip_fcntl(lSocketRecv, F_SETFL, lwip_fcntl(lSocketRecv, F_GETFL, 0) | O_NONBLOCK);
lwip_listen(lSocketRecv, 128);

while (1)
{
os_dly_wait(100);
lAddrSize = sizeof(sListenAddr);
new_fd = lwip_accept(lSocketRecv, (struct sockaddr *)&sListenAddr, &lAddrSize);
lwip_write(new_fd, "Welcome to the jungle\n\n\r>", 25);
str_tcpTty.active = 1;
while (1)
{
nbytes = lwip_read(new_fd, &buffer[u16L_buffPtr], 1);
if (nbytes > 0)
{
u16L_buffPtr += nbytes;
if (buffer[u16L_buffPtr-1] == 'q') // q ends the session
break; // Terminate session

if (!testParseBuff((char *)buffer, u16L_buffPtr, &str_tcpTty)) // complete command found and parsed
{
u16L_buffPtr = 0;
lwip_write(new_fd, "\r>", 2);
}
}

os_dly_wait(6);
}
str_tcpTty.active = 0;
u16L_buffPtr = 0;
lwip_close(new_fd);
}
}

At the moment we can manage without nonblocking sockets using lwip_setsockopt() to set a timeout for the socket, but we are still curious as to why nonblocking-sockets don't work for us.

Best regards
/Åke

-----Ursprungligt meddelande-----
Från: lwip-users-bounces+ake.forslund=nib...@nongnu.org [mailto:lwip-users-bounces+ake.forslund=nib...@nongnu.org] För Simon Goldschmidt
Skickat: den 13 mars 2012 09:06
Till: Mailing list for lwIP users
Ämne: Re: [lwip-users] Nonblocking sockets problem

Simon Goldschmidt

unread,
Mar 14, 2012, 4:59:30 AM3/14/12
to Mailing list for lwIP users
"Åke Forslund" <Ake.Fo...@nibe.se> wrote:
> Hi again, this is not the original code but a implementation of the
> problem in our simple telnet-server for debug. Code below. In our original code
> we use ioctlsocket() to set non-blocking but using lwip_ fcntl() makes no
> difference.

The code you sent works for me with one slight modification: you have to check the return value of lwip_accept() to be >= 0 to enter the first while(1) loop. Better yet, use select to see if accept will succeed (put lSocketRecv on the readset).

You don't check the return value of lwip_accept() although calling it on a nonblocking socket: unless there's actually a new connection pending -1 will be returned. Then of course, the inner while(1) loop is never exited because you will never receive 'q' without a client (lwip_read() always returns -1 as new_fd is -1).

Simon
--
Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir
belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de

Åke Forslund

unread,
Mar 14, 2012, 6:17:46 AM3/14/12
to Mailing list for lwIP users
I see my mistake there, however even with code that is at least theoretically sane I can't establish a connection. lwip_accept() always returns EWOULDBLOCK for me.

from socket debug:
lwip_accept(0)...
lwip_accept(0): returning EWOULDBLOCK
[Repeats forever]

putty reports "Connection closed by remote host" followed by "Network error: Software caused connection abort" or "Connection reset by Peer"

So it seems I've made some mistake elsewhere as well. Maybe Putty isn't the best tool to test this and I have to write some simple socket-script/program to check this thoroughly. I'll go back and check API_EVENT() macro as well and try to wrap my head around what is supposed to happen.

Thanks for all the help
/Åke

-----Ursprungligt meddelande-----
Från: lwip-users-bounces+ake.forslund=nib...@nongnu.org [mailto:lwip-users-bounces+ake.forslund=nib...@nongnu.org] För Simon Goldschmidt
Skickat: den 14 mars 2012 10:00
Till: Mailing list for lwIP users
Ämne: Re: [lwip-users] Nonblocking sockets problem

gold...@gmx.de

unread,
Mar 14, 2012, 2:26:10 PM3/14/12
to Mailing list for lwIP users
Åke Forslund wrote:
> I see my mistake there, however even with code that is at least theoretically sane I can't establish a connection. lwip_accept() always returns EWOULDBLOCK for me.
>
> from socket debug:
> lwip_accept(0)...
> lwip_accept(0): returning EWOULDBLOCK
> [Repeats forever]
>
> putty reports "Connection closed by remote host" followed by "Network error: Software caused connection abort" or "Connection reset by Peer"

I have pasted your code into test.c in the Win32 port from contrib,
removed your application-specific code, checked the return value of
lwip_accept() and I could successfully connect using telnet.exe provided
with windows XP.

If it's not working for you, that suggests a problem either in your
port or in the client application, I guess... What are the thread
priorities in your system? Are you sure there is only one thread active
in lwIP at a time? Because that's the main difference between the
blocking and your non-blocking version: the blocking version just sits
there and waits for a callback that lets lwip_accept return, while the
non-blocking version calls into tcpip_thread *very* often - if your
threading is broken, there's a good chance this will be revealed by your
way of using non-blocking sockets.

Simon

Åke Forslund

unread,
Mar 15, 2012, 4:25:24 AM3/15/12
to Mailing list for lwIP users
Thanks Simon,

it's good to know that the code should work. Threadpriorities are: tcpip-thread (and all threads created by lwip I think) has a higher prio than the application thread. The telnet thread is not the only thread running, I have a thread handling changes in the network (link down, etc.) running and some threads not related to lwip at all. I'll modify my system to only launch the essential threads and retest. I better look into my porting layer to make sure my priority assignment-scheme is as sane as I think it is.

Thanks for the hints, I'll test some more and try to figure out what I have done wrong.

/Åke

-----Ursprungligt meddelande-----
Från: lwip-users-bounces+ake.forslund=nib...@nongnu.org [mailto:lwip-users-bounces+ake.forslund=nib...@nongnu.org] För gold...@gmx.de
Skickat: den 14 mars 2012 19:26
Till: Mailing list for lwIP users
Ämne: Re: [lwip-users] Nonblocking sockets problem

Reply all
Reply to author
Forward
0 new messages