[comp.unix.programmer] why would a socket read

mlevin@jade.tufts.edu (06/28/91)

   I am doing a read() on a connected TCP socket (BSD 4.3) marked as
non-blocking. For some reason, the read returns the proper number of
characters read (or sometimes 0), but sets errno to EWOULDBLOCK. Why
is this? My program never did this before; I was under the impression
that if no data was available, it should return -1. Is this a possible
event, or am I trashing memory somewhere? Please reply to
mlevin@jade.tufts.edu. 

Mike Levin

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/28/91)

In article <1991Jun27.220701.21108@athena.mit.edu> mlevin@jade.tufts.edu writes:
>    I am doing a read() on a connected TCP socket (BSD 4.3) marked as
> non-blocking. For some reason, the read returns the proper number of
> characters read (or sometimes 0), but sets errno to EWOULDBLOCK.

The Golden Errno Rule:

	He who inspects errno before a system call returns failure
	shall be buried before he is dead.

---Dan

6sigma2@polari.UUCP (Brian Matthews) (06/28/91)

In article <1991Jun27.220701.21108@athena.mit.edu> mlevin@jade.tufts.edu writes:
|   I am doing a read() on a connected TCP socket (BSD 4.3) marked as
|non-blocking. For some reason, the read returns the proper number of
|characters read (or sometimes 0), but sets errno to EWOULDBLOCK.

Errno is only valid if the read fails.  If the read succeeds, the
value of errno shouldn't be used.
-- 
Brian L. Matthews	blm@6sceng.UUCP

bridej@sequent.com (Jim Bride) (06/29/91)

mlevin@jade.tufts.edu writes:


>   I am doing a read() on a connected TCP socket (BSD 4.3) marked as
>non-blocking. For some reason, the read returns the proper number of
>characters read (or sometimes 0), but sets errno to EWOULDBLOCK. Why
>is this? My program never did this before; I was under the impression
>that if no data was available, it should return -1. Is this a possible
>event, or am I trashing memory somewhere? Please reply to
>mlevin@jade.tufts.edu. 

According to the man page, when you set the descriptor for the socket as
non-blocking (ie with the FNDELAY flag to fcntl()), the read will return
EWOULDBLOCK to let you know that the operation would have blocked had under
normal circumstances.  You read definitely should be returning -1 (at least
this is how it works under Dynix and SunOS.)   It sounds like there might be
a bug in read() on your machine.  I'd be interested to find out what was
causing your problem.
 
>Mike Levin

- Jim Bride	bridej@sequent.com	
----------------------------------------------------------------------------

hwajin@sgi.com (Hwa-jin Bae) (06/29/91)

>>>>> On 28 Jun 91 04:31:48 GMT, 6sigma2@polari.UUCP (Brian Matthews) said:

Brian> |   I am doing a read() on a connected TCP socket (BSD 4.3) marked as
Brian> |non-blocking. For some reason, the read returns the proper number of
Brian> |characters read (or sometimes 0), but sets errno to EWOULDBLOCK.

Brian> Errno is only valid if the read fails.  If the read succeeds, the
Brian> value of errno shouldn't be used.


i think the original poster is knowledgable enough to know that.
read() on a non-blocking socket can still return EWOULDBLOCK if
the amount of bytes read is less than the amount of bytes requested.
usually, programs that do non-blocking I/O would ignore this error
and try again, if necessary.



*hwajin


--
protocol engines, inc.

guy@auspex.auspex.com (Guy Harris) (06/30/91)

>Brian> |   I am doing a read() on a connected TCP socket (BSD 4.3) marked as
>Brian> |non-blocking. For some reason, the read returns the proper number of
>Brian> |characters read (or sometimes 0), but sets errno to EWOULDBLOCK.
>
>Brian> Errno is only valid if the read fails.  If the read succeeds, the
>Brian> value of errno shouldn't be used.
>
>i think the original poster is knowledgable enough to know that.
>read() on a non-blocking socket can still return EWOULDBLOCK if
>the amount of bytes read is less than the amount of bytes requested.

Your second sentence contradicts your first, if I'm correctly
interpreting the second sentence as saying "a read on a non-blocking
socket can read some non-zero number of bytes less than the number of
bytes requested, return as its return value the number of bytes
returned, *and* set 'errno' to EWOULDBLOCK."

Of the two, I'll go for the first sentence, given that in many UNIX
implementations - all the ones with which I'm familiar - "errno" is set
by a lump of code that also forces the return value of the routine that
did the trap to be -1.

I.e., if "errno" is set, -1 is returned, period, end of discussion.

There may well be implementations where that's not done, but the SunOS
implementation works that way on 68K and SPARC machines (and probably
386i's as well), as does the 4.3-reno implementation on VAX, Tahoe, 68K,
and i386) and the System V Release 3 implementation on the WE32K.  (In
fact, the lump of code in question is good old "cerror" - modulo the
presence or absence of some number of leading underscores - a name
dating, as I remember, all the way back to the PDP-11....)

Yes, a "read()" on a non-blocking socket can return a byte count lower
than the number of bytes requested.  So can a "read()" on a blocking
socket, or on a plain ordinary boring file, for that matter.  However,
in *NO* UNIX implementation with which I'm familiar will it change the
value of "errno" if it does that!

I.e., if "read()" doesn't return -1, *don't assume "errno" is telling
you anything about the read* - it's almost certainly *not* doing so.  If
it *happens* to contain EWOULDBLOCK, that's because the last call that
*did* return an error indication set it to EWOULDBLOCK, whatever that
call was....

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (07/01/91)

In article <1991Jun27.220701.21108@athena.mit.edu>, mlevin@jade.tufts.edu writes:

> I am doing a read() on a connected TCP socket (BSD 4.3) marked as
> non-blocking.  For some reason, the read returns the proper number of
> characters read (or sometimes 0), but sets errno to EWOULDBLOCK.

You must be mistaken about something.  4.3 read() never sets errno
unless it returns -1.  In support of this, the source, stripped of
junk:

	#include "SYS.h"
	SYSCALL(read)
		ret

After preprocessing, this expands into

		.globl	cerror
	err:	jmp	cerror
		.globl	_read
		.align	2
	_read:	.word 0
		chmk	$3
		jcs	err
		ret

In another file, we have

		.globl	_errno
	cerror:
		movl	r0,_errno
		mnegl	$1,r0
		ret

Notice that errno is never affected except under circumstances which
cause read to return -1.  (The kernel does not have direct access to
the user-level errno variable.)

(Before you take me to task for citing assembly code, note that 4.3
requires a VAX to run.  If you're not on a VAX, you're running either
something later - 4.3-tahoe is an example - or something else, perhaps
a derivative or port of 4.3.)

Are you sure you're really using 4.3, not a 4.3 derivative of some
sort?

For that matter, are you sure it's setting errno?  The errno value
might be left over from something else.

Besides all that, if read() doesn't return an error, the value of errno
is unspecified; it may be EWOULDBLOCK, it may be EFAULT, it may be
ELOOP, for that matter.  The value of errno is *not meaningful* except
after a failed call documented to set errno and before the next call
which does not promise to preserve errno.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu