#550 assigned defect

fcntl() fails to put a non-blocking socket into blocking mode

Reported by: Thomas Rauscher Owned by: Joel Sherrill
Priority: normal Milestone: 6.1
Component: network/legacy Version: 4.5
Severity: major Keywords:
Cc: bugs@…, joel.sherrill@… Blocked By:
Blocking:

Description (last modified by Joel Sherrill)

A socket cannot be put into blocking mode using fcntl()
once it has been put into non-blocking mode.

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.

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.

Release:
RTEMS-4.5

Environment:
rtems-4.5.0, newlib-1.10 or newlib-1.11

Attachments (1)

socketblock.c (6.7 KB) - added by Thomas Rauscher on Dec 3, 2006 at 1:31:12 PM.
socketblock.c

Download all attachments as: .zip

Change History (8)

comment:1 Changed on Jan 16, 2004 at 6:01:54 PM by Joel Sherrill

Status: assignedwaiting

State-Changed-From-To: open->feedback
State-Changed-Why: Thomas .. does this happen in 4.6 or the currect source?

I don't see this problem in the current code. At this
point, no further releases from the 4.5 branch are planned
so I am prone to close any bug report against it.

Changed on Dec 3, 2006 at 1:31:12 PM by Thomas Rauscher

Attachment: socketblock.c added

socketblock.c

comment:2 Changed on Nov 22, 2014 at 2:23:02 PM by Gedare

Description: modified (diff)
Milestone: 24.9.5

comment:3 Changed on Nov 22, 2014 at 2:24:39 PM by Gedare

Owner: changed from Eric Norum to Joel Sherrill

comment:4 Changed on Nov 23, 2014 at 6:52:45 PM by Joel Sherrill

I am hacking together a test but I believe this does happen in the current source. It looks like so_ioctl(fd, FIONBIO, [O_NONBLOCK|~O_NONBLOCK]) needs to be called. We have the ioctl_h handler but should we make the call if networking is enabled?

comment:5 Changed on Nov 23, 2014 at 6:56:06 PM by Joel Sherrill

NOTE that FIONBIO is not defined in newlib -- only in the network stack so that makes for some trouble. I suppose we could modify rtems_syscalls.c to handle F_SETFD.

comment:6 Changed on Feb 12, 2015 at 5:46:49 PM by Joel Sherrill

Description: modified (diff)
Milestone: 4.9.55.0

This is a known issue with many RTOS'. The FACE (http://www.opengroup.org/face) standard has specifically had to add requirements so this behavior is required of RTOSes conforming to the FACE POSIX Profiles. The ioctl() interface is not in POSIX and fcntl() is the only way to set non-blocking in a pure POSIX environment.

I pushed this milestone to 5.0 because:

  • this is a long-standing issue.
  • it is technically beyond the POSIX standard itself.
  • it will need to be addressed with the current IPV4 stack, the new IPV4/IPV6 stack and LWIP if we are to support that.
  • this needs test code.
  • this needs a design that can work with multiple network stacks.

comment:7 Changed on Nov 9, 2017 at 6:26:42 AM by Sebastian Huber

Milestone: 5.06.1

Milestone renamed

Note: See TracTickets for help on using tickets.