Advice on streams and bsd sockets

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Advice on streams and bsd sockets

Michael Jones-2
I am looking for some advice on using streams with sockets. I am using CYGPKG_NET and taking the socket handle and creating a stream with fdopen().

A fwrite() eventually arrives in this code:

static int
bsd_lseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence)
{
    return ESPIPE;
}

And this causes an error, but a second call to fwrite() works. It always happens when there is a fwrite() immediately after a fread(), as that triggers the seek.

I am looking for advice on how to handle this problem.

Of course I could not use streams, but I am working with lua 5.2.3 and it is based on streams, and don't want to modify it that much. I also can't turn off buffering, because lua relies on the ability to push bytes back into the stream after reading them.

Does anyone have a patch that works around the problem or know of some other way to create a stream that does not rely on seek? In the case where I use it, there is no need for seek anyway. I am using the stream in place of stdin and stdout so that lua can interact with a telnet session.

Mike

--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

Reply | Threaded
Open this post in threaded view
|

Re: Advice on streams and bsd sockets

Grant Edwards-6
On 2014-01-21, Michael Jones <[hidden email]> wrote:

> I am looking for some advice on using streams with sockets. I am using CYGPKG_NET and taking the socket handle and creating a stream with fdopen().
>
> A fwrite() eventually arrives in this code:
>
> static int
> bsd_lseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence)
> {
>     return ESPIPE;
> }
>
> And this causes an error, but a second call to fwrite() works. It
> always happens when there is a fwrite() immediately after a fread(),
> as that triggers the seek.
>
> I am looking for advice on how to handle this problem.

What I would do is first add a diag_printf() to bsd_lseek() to print
out the paramters so you can see exactly what sort of seek is being
attempted.  You could add a bit of code to bsd_lseek() to check for
(and return success for) "noop" operations (e.g. seek to 0 offset from
current location).

> Of course I could not use streams, but I am working with lua 5.2.3
> and it is based on streams, and don't want to modify it that much. I
> also can't turn off buffering, because lua relies on the ability to
> push bytes back into the stream after reading them.
>
> Does anyone have a patch that works around the problem or know of
> some other way to create a stream that does not rely on seek? In the
> case where I use it, there is no need for seek anyway. I am using the
> stream in place of stdin and stdout so that lua can interact with a
> telnet session.

If the code works OK with stdin/stdout streams, then the lseek() calls
must not be actually doing anything, right?  If that's the case, then
it should be easy enough to modify the the bsd_lseek() function to do
the same.

--
Grant Edwards               grant.b.edwards        Yow! I haven't been married
                                  at               in over six years, but we
                              gmail.com            had sexual counseling every
                                                   day from Oral Roberts!!


--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

Reply | Threaded
Open this post in threaded view
|

Re: Advice on streams and bsd sockets

Michael Jones
The lseek simply deals with the read buffer and sets position to 0. I tried to swallow the error, but there is some strange artifact left over that causes telnet to print a ^M. When I tracked that down, it was related telnet failing to negotiate because writes were not working. I did not track down how it broke write. I am guessing that the problem is just that no one expected streams to be used with the networking and it probably needs more work than I have time.

I tried an alternate solution. I used two streams, one for read, and one for write. This even worked well in the case where my telnetd was using the file descriptor to handled telnet configuration and streams were used for lua. As long as lua is flushing, they coexist properly.

But two streams sharing a file descriptor create a new problem. I need to close both streams to release resources because in a telnet environment people log out and log back in. When the streams use the same file descriptor, the second close returns an error and resources are not freed. The error comes from the first close which also closes the file descriptor.

I modified fclose to free resources even when there is an error, but that may not be POSIX behavior or may have side effects.

Does anyone know in general if streams can share a file descriptor in other systems and all be closed properly? If this is the expected behavior, it is probably easier to modify fclose than to solve the seek problem. It is also a more natural solution because lua was already setup for stdin and stdout and two streams match the way the code is structured.

For those interested, my telnetd package with command line support including lua will be available for others to use. It is part of my Cortex A9 work for iMX6 SMP hal. Sooner or later someone will post the link on the ecos site.

Mike


On Jan 21, 2014, at 8:10 AM, Grant Edwards <[hidden email]> wrote:

> On 2014-01-21, Michael Jones <[hidden email]> wrote:
>> I am looking for some advice on using streams with sockets. I am using CYGPKG_NET and taking the socket handle and creating a stream with fdopen().
>>
>> A fwrite() eventually arrives in this code:
>>
>> static int
>> bsd_lseek(struct CYG_FILE_TAG *fp, off_t *pos, int whence)
>> {
>>    return ESPIPE;
>> }
>>
>> And this causes an error, but a second call to fwrite() works. It
>> always happens when there is a fwrite() immediately after a fread(),
>> as that triggers the seek.
>>
>> I am looking for advice on how to handle this problem.
>
> What I would do is first add a diag_printf() to bsd_lseek() to print
> out the paramters so you can see exactly what sort of seek is being
> attempted.  You could add a bit of code to bsd_lseek() to check for
> (and return success for) "noop" operations (e.g. seek to 0 offset from
> current location).
>
>> Of course I could not use streams, but I am working with lua 5.2.3
>> and it is based on streams, and don't want to modify it that much. I
>> also can't turn off buffering, because lua relies on the ability to
>> push bytes back into the stream after reading them.
>>
>> Does anyone have a patch that works around the problem or know of
>> some other way to create a stream that does not rely on seek? In the
>> case where I use it, there is no need for seek anyway. I am using the
>> stream in place of stdin and stdout so that lua can interact with a
>> telnet session.
>
> If the code works OK with stdin/stdout streams, then the lseek() calls
> must not be actually doing anything, right?  If that's the case, then
> it should be easy enough to modify the the bsd_lseek() function to do
> the same.
>
> --
> Grant Edwards               grant.b.edwards        Yow! I haven't been married
>                                  at               in over six years, but we
>                              gmail.com            had sexual counseling every
>                                                   day from Oral Roberts!!
>
>
> --
> Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
> and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
>


--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss