Subject: kern/11836: Non-blocking BPF read returns 0, not -1 with EWOULDBLOCK, if no data
To: None <gnats-bugs@gnats.netbsd.org>
From: None <guy@alum.mit.edu>
List: netbsd-bugs
Date: 12/28/2000 14:52:12
>Number:         11836
>Category:       kern
>Synopsis:       Non-blocking BPF read returns 0, not -1 with EWOULDBLOCK, if no data
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Dec 28 14:52:00 PST 2000
>Closed-Date:
>Last-Modified:
>Originator:     Guy Harris
>Release:        -current
>Organization:
>Environment:
(Bug found by code inspection and from FreeBSD and OpenBSD changes to
address the same problem.)
>Description:
A read on a BPF device in non-blocking mode will, if no data is
available to be read, return 0, rather than returning -1 and
setting "errno" to EWOULDBLOCK.

The FreeBSD change for this notes that this causes problems with
threaded programs; their userland threads package puts file descriptors
into non-blocking mode, and expects I/O that would block to return
-1 and set "errno" to EWOULDBLOCK - it uses this as an indication that
the thread doing the I/O operation should be put to sleep.
>How-To-Repeat:

>Fix:
The following patch to "syssrc/sys/net/bpf.c" picks up the OpenBSD
fix for this.

Index: bpf.c
===================================================================
RCS file: /cvsroot/syssrc/sys/net/bpf.c,v
retrieving revision 1.59
diff -c -r1.59 bpf.c
*** bpf.c	2000/12/12 17:55:21	1.59
--- bpf.c	2000/12/28 22:49:39
***************
*** 434,441 ****
  		if (d->bd_rtout != -1)
  			error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
  					  d->bd_rtout);
! 		else
! 			error = EWOULDBLOCK; /* User requested non-blocking I/O */
  		if (error == EINTR || error == ERESTART) {
  			splx(s);
  			return (error);
--- 434,446 ----
  		if (d->bd_rtout != -1)
  			error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
  					  d->bd_rtout);
! 		else {
! 			if (d->bd_rtout == -1) {
! 				/* User requested non-blocking I/O */
! 				error = EWOULDBLOCK;
! 			} else
! 				error = 0;
! 		}
  		if (error == EINTR || error == ERESTART) {
  			splx(s);
  			return (error);
***************
*** 1198,1205 ****
  }
  
  /*
!  * Attach an interface to bpf.  driverp is a pointer to a (struct bpf_if *)
!  * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
   * size of the link header (variable length headers not yet supported).
   */
  void
--- 1203,1209 ----
  }
  
  /*
!  * Attach an interface to bpf.  dlt is the link layer type; hdrlen is the fixed
   * size of the link header (variable length headers not yet supported).
   */
  void

>Release-Note:
>Audit-Trail:
>Unformatted: