[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lwip-users] sock_set_errno semantics in lwip 2.1.2
From: |
address@hidden |
Subject: |
Re: [lwip-users] sock_set_errno semantics in lwip 2.1.2 |
Date: |
Wed, 19 May 2021 13:27:06 +0200 (CEST) |
Hi there Simon,
thanks for your timely answer!
I'm sorry, but this can NOT be the solution. First of all, a global variable to
carry shared error conditions was a pretty bad idea when it was incepted, but
in these days where even the smallest of systems employs
multithreading/processing and/or multiple communication channels, you can't get
any more stone age than falling back to a global errno.
Second, threads and sockets are per se not related. There is nothing that
prevents a process to serve multiple sockets; thus, on thread local storage,
you would have to keep instance data for each socket. Likewise, even though (at
least in 1.4.1), sharing sockets among tasks was not supported, it can be done
under certain conditions. In those cases TLS (which FreeRTOS does NOT support,
by the way) wouldn't help either.
In short, a socket based error code MUST be kept in the socket. Everything else
won't work reliably in any multitasking environment.
I don't know why it was considered a bug in 1.4.1. It worked well for several
of my customers in hundreds of installations in the field, and it was the right
thing to do.
I don't mind recoding for 2.x, but there MUST be a socket local error code to
maintain. If that doesn't appear to be possible, we must abandon lwip.
Am 19.05.2021 um 12:01 schrieb Ruediger_Asche@t-online.de:
> Hi there, we have been using lwip in a FreeRTOS based firmware for many
> years now and are upgrading from lwip 1.4.1 to 2.1.2.
>
>
>
> We are using the following (pseudo)code to encapsulate recv() in a C++
> class:
>
>
>
> do
> {
> int aCurrentCount = recv(<socket instance>,<ptr into recv
> buffer>,aCharsRequested,theTimeout?MSG_DONTWAIT:0);
> if (aCurrentCount>0)
> {
> <there were characters received from the socket, handle>
> }
> else
> {
> socklen_t aReturnSize = sizeof(aError);
> int aError;
> getsockopt(<socket instance>, SOL_SOCKET, SO_ERROR,(void
> *)&aError,&aReturnSize);
> if (!aCurrentCount || (aCurrentCount<0 && (aError!= EWOULDBLOCK)))
> {
> < connection gone down, close the socket, return failure or
> partial read if applicable>
> }
> }
> } < until timeout occurred or all requested characters have been received>
>
>
>
> On 1.4.1 this worked fine. On 2.1.2, every recv() falls into the close
> socket case.
>
>
>
> I debugged this and found that in 2.1.2, sock_set_errno() has been
> rewritten to not set the connection specific error code member
> pending_err but the global variable errno.
>
> The getsockopt funtion, though, retrieves the pending_err member which
> hasn't been set by sock_set_errno.
>
>
>
> Needless to say, in a multi tasking, multiple socket environment it is
> not feasible to use a global variable for connection specific errors, so
> I can't look at the global errno to determine the failure code for this
> socket.
>
>
>
> 1.4.1 implemented the sock_set_errno macro to store the error in a
> socket specific variable.
>
>
>
> If there is a thread safe and per-socket way to implement the above
> sequence, how do I need to rewrite the code? If not, I consider the
> implementation a bug, how to report this?
The actual bug was in 1.4.1 to not store such error codes in 'errno'.
The socket API is not under our control, we try to stay to the opengroup
spec as close as possible.
Of course, you cannot use a simple global variable for 'errno' when
using multithreading. You need something like "thread local storage",
which I believe FreeRTOS should support.
Regards,
Simon