(Non)-Blocking sockets using fcntl()

Thomas Rauscher trauscher at loytec.com
Mon Dec 15 16:02:21 UTC 2003


Hi,

I've found a problem with putting sockets into blocking/non-blocking
mode using fcntl() in rtems-4.5.0 and probably also rtems-4.6.0pre5.
ioctl() is working fine, so the problem is not in the IP stack.

The problem occurs in real life with the GoAhead webserver on 
high-latency connections as its non-blocking write socket remains
non-blocking and a web page can be truncated when websDone() is called.

There have been several threads on this topic, so I hope this
is really a new issue.

In newlib (1.10, 1.11) there are several non-blocking flags.
The following is defined in sys/fcntl.h

#define _FNBIO          0x1000  /* non blocking I/O (sys5 style) */
#define _FNONBLOCK      0x4000  /* non blocking I/O (POSIX style) */
...
#define _FNDELAY        _FNONBLOCK      /* non blocking I/O (4.2 style)
*/
/*      O_NDELAY        _FNDELAY        set in include/fcntl.h */

/*      O_NDELAY        _FNBIO          set in 5include/fcntl.h */

#define O_NONBLOCK      _FNONBLOCK


So O_NDELAY is never defined. sys/fcntl.h is not
patched by the rtems-newlib patch.

In RTEMS, libio.c and libio_.h both contain the following code

#if ! defined(O_NDELAY)
# if defined(solaris2)
#  define O_NDELAY O_NONBLOCK
# elif defined(RTEMS_NEWLIB)
#  define O_NDELAY _FNBIO
# endif
#endif

As O_NDELAY is undefined and RTEMS_NEWLIB is defined,
O_NDELAY is defined to 0x1000.

Thus, using O_NONBLOCK in fcntl() (this was suggested
in the mailing list some time ago) doesn't seem to work. 

There are several workarounds/solutions:
 - Define O_NDELAY to O_NONBLOCK in libio (like the newlib would
   do if one of the line were not commented out).
   Probably this is the cleanest solution but maybe has side-effects
   when BSD/SYSV/POSIX code is mixed.
 - Don't use fcntl() with O_NONBLOCK on sockets in RTEMS.
   This means to fix the call to fcntl() in the web server and
   probably other applications I'm not aware of.
   In the web server it would be sufficient to let RTEMS use
   the ECOS variant in socketSetBlock(). I've tested this.
 - Add some logic to the libio/fcntl flags mapping. This could
   be problematic if flags are set inconsistently, e.g.
   O_NONBLOCK set, _FNBIO not set.

Maybe somebody can confirm this and/or comment my proposed fixes.

If somebody has other patches for this issue, I can test them
(as long as they can be applied to RTEMS 4.5).

Best regards,
Thomas Rauscher

-- 
Thomas Rauscher
LOYTEC electronics GmbH
Stolzenthalergasse 24/3
A-1080 Wien
Austria/Europe
trauscher at loytec.com
www.loytec.com
Phone: +43-1-4020805-15
FAX:   +43-1-4020805-99




More information about the users mailing list