bug-glibc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: FW: Recv/Read problem


From: Andrew Snare
Subject: Re: FW: Recv/Read problem
Date: Wed, 09 May 2001 10:59:46 +0200

You wrote:
"Josh Percival" <address@hidden> writes:

> I would like to ask a question about the behaviour of a particular system
> call that is giving me unexpected and undetermined results that could be a
> bug or incorrect behaviour.
>
> a call to Recv or Read on a socket connected to a windows machine returns
> ESPIPE in errno.

ESPIPE looks strange.

It does. According to the documentation I could find, it gets returned if an attempt is make to seek on a pipe. However, we're not doing this. We're just making a call to recv/read.

> I was wondering whether this is correct behaviour and under which
> circumstances occurs since I couldn't find any reference to it in the man
> pages. If you have any information that may help or if this is a known bug
> for the version I am using could you please let me know.

Glibc comes with a manual that should explain all this,

The glibc info pages (and system man pages) don't list ESPIPE as a possible return code for these calls.

I should mention that digging around the kernel source (for 2.2) shows that ESPIPE is returned from within the socket reading code if an attempt is made to read from an offset that is not the current position. According to Richard Gooch's 2.0 -> 2.2 porting guide, the file-descriptor read code generalised to support the pread/pwrite operations which allow for an "offset" parameter when reading. He further recommends the following code to sanity check reads on pipe-like file-descriptors:

[start quote]
Another thing to take note of is that Linux 2.2 introduces the pread() and pwrite() system calls. These allow a process to read and write from a specified position in a file. This is similar, but not identical, to using the lseek() system call followed by an ordinary read() or write() system call. In particular, concurrent access to a file (required for asynchronous I/O (AIO) support) requires the pread() and pwrite() system calls. To support these new system calls, a new parameter (the 4th or final parameter) is supplied to the read() and write() methods. This parameter is a pointer to an offset, which may be updated. As a device driver writer, you don't care about file positions, so you could ignore this parameter. For correctness, however, you should prevent the use of the new system calls for your driver, just as you don't support the llseek() method. You can do this by adding the following line at the top of your read() and write() methods:
        if (ppos != &file->f_pos) return -ESPIPE;
assuming that ppos is the variable name of the offset pointer and file is the variable name of the struct file pointer. This code depends on the fact that normal read() and write() system calls will pass the address of file->f_pos as the offset pointer, but the pread() and pwrite() system calls will pass the address of the variable passed in via the system call. Hence it is easy to distinguish between the two cases.
[end quote]

The source of our ESPIPE would appear to be this test within the kernel socket code. What I don't understand, however, is how a situation could ever arise whereby read/recv would trigger this condition. I tried to trace the glibc source code through to the system call interface but a generic assembler thunk that I didn't quite follow was used.

Hence I'm not sure if this is really a glibc error (for somehow causing this condition to be triggered), a kernel error (for returning this error code when this call is made) or a problem with our code (for somehow triggering this behaviour). I personally find socket code tricky and can't be sure the latter is not true, but am pretty sure it's clean; I only wish I could produce a small test-case that demonstrates the behaviour in isolation.

Thanks in advance for any information that people might have about this problem. Regards,

 - Andrew





reply via email to

[Prev in Thread] Current Thread [Next in Thread]