Getting value of file pointer for socket, OR am I blocked on a write?

Getting value of file pointer for socket, OR am I blocked on a write?

Post by Doug Siebe » Fri, 07 May 1993 13:41:32



I've got a program that communicates with users directly through TCP stream
sockets using the stdio libraries (had to write my own putchar macro that
writes a \r\n for a \n and my own printf that calls vsprintf then my putchar
macro, fun fun)  There is an alarm signal received every five minutes, which
will of course interrupt system calls.  Since the program would be unworkable
in its current form otherwise, the system calls are always restarted after
the signal completes (its HP-UX, I have a choice of which behavior I want)

The situation is this:  When a user far away loses their connection due to
routing problems, my program of course cannot know this.  My problem is that
if my program is writing stuff to this user, it will pile up and eventually
the write will block due to the socket buffer being full.  I'd like for my
every-five-minute alarm signal to check and see if the process was interrupted
while blocked on a write -- if it is blocked in the same write two consecutive
alarms I'll assume the connection is mucked up and drop it to avoid wasting
resources.  I can be a bit tricky/* and access the stdout->__cnt field and
see if there is stuff in the stdout buffer ready to be written.  I'd like to
access the file pointer of the socket.  fgetpos(3), ftell(3), and lseek(2) all
work fine for ttys, but don't work for sockets.  If I could get this
information for the socket I could compare and if there is stuff in the stdout
buffer two consecutive times but the file pointer is the same I could decide
to terminate that connection.

I know this information exists somewhere, the HP-UX program 'monitor' can
examine a process and show various information about it, including the files
that are open and their current file position.  It shows the values when I
examine my program, they are in there somewhere, I just can't figure out how
to get at them.  Anyone know how?  Is it portable to other systems?  Or,
alternatively, can you figure out a better way to do what I want to do?  I
can't send anything to the user, that'll cause problems, I have to be able
to do it from the state available to my program, without grunging in the
kernel.

Thanks for any ideas/suggestions!

--
/-----------------------------------------------------------------------------\
| Doug Siebert                             | "I don't have to take this abuse |


|     ICBM:  41d 39m 55s N, 91d 30m 43s W  |  me!"  Bill Murray, Ghostbusters |
\-----------------------------------------------------------------------------/

 
 
 

Getting value of file pointer for socket, OR am I blocked on a write?

Post by George MacDona » Sat, 08 May 1993 08:55:12



>I've got a program that communicates with users directly through TCP stream
>sockets using the stdio libraries (had to write my own putchar macro that
>writes a \r\n for a \n and my own printf that calls vsprintf then my putchar
>macro, fun fun)  There is an alarm signal received every five minutes, which
>will of course interrupt system calls.  

        Ug, alarms, signals! yick, make it event driven! No messy partial
        writes, or other such rude interuptions to worry about.

Quote:> Since the program would be unworkable
>in its current form otherwise, the system calls are always restarted after
>the signal completes (its HP-UX, I have a choice of which behavior I want)

        Oh well if you must it can be done this way! Event driven is much
        better.

Quote:>The situation is this:  When a user far away loses their connection due to
>routing problems, my program of course cannot know this.  

        Well it can, you need to setup for sigpipe's. But even this only
        works if you keep writting on the socket after the far end is gone.

Quote:>My problem is that
>if my program is writing stuff to this user, it will pile up and eventually
>the write will block due to the socket buffer being full.  

        You could setup the socket as nonblocking I/O type. Then if you
        try to write and it would fail, you will get an error EWOULDBLOCK.
        You'll have to add a little bit of code to deal with partial
        writes/sends, but then you could drop the alarm stuff and simply check
        the wall clock. If you don't have anything else todo while your waiting
        you can simply sleep for a while and then try again. This can be
        done either with a sleep() call or by using select to wait on the
        outbound stream. If you also need to check for input from the far
        end, setup the select call with the input fd AND the output fd.

Quote:>I'd like for my
>every-five-minute alarm signal to check and see if the process was interrupted
>while blocked on a write -- if it is blocked in the same write two consecutive
>alarms I'll assume the connection is mucked up and drop it to avoid wasting
>resources.  I can be a bit tricky/* and access the stdout->__cnt field and
>see if there is stuff in the stdout buffer ready to be written.  I'd like to
>access the file pointer of the socket.  fgetpos(3), ftell(3), and lseek(2) all
>work fine for ttys, but don't work for sockets.  If I could get this
>information for the socket I could compare and if there is stuff in the stdout
>buffer two consecutive times but the file pointer is the same I could decide
>to terminate that connection.

Can't do this, the socket is like a pipe, not a file.

Quote:

>I know this information exists somewhere, the HP-UX program 'monitor' can
>examine a process and show various information about it, including the files
>that are open and their current file position.  It shows the values when I
>examine my program, they are in there somewhere, I just can't figure out how
>to get at them.  Anyone know how?  Is it portable to other systems?  Or,
>alternatively, can you figure out a better way to do what I want to do?  I
>can't send anything to the user, that'll cause problems, I have to be able
>to do it from the state available to my program, without grunging in the
>kernel.

Using nonblocking I/O works fine on almost all socket style TCP implementation
that I have used, including SunOS, HP, AIX, ... One problem with it is
the partial writes, TLI supports atomic writes, i.e. either it takes the
whole thing or it returns immediatly and takes nothing. However TLI is
not quite as portable as sockets although this is changing quickly with V.4

Another approach is to add a protocol on top of all this, add ack/nack's
and then discover just how slow a tcp connection gets when you alternatly
read and write to a far end process! If you do this you start conflicting
with the smart buffer cacheing in the TCP layer, it delays writing for a
while trying to get an optimal size buffer full. At which point you either
go to unreliable IP or add sliding windows!  Stick to the above is simpler.

Hope this helps,