vi, threading, EAGAIN, nonblocking (was: Error: input: Resource temporarily unavailable)

Mark Terribile materribile at yahoo.com
Sat Jun 5 01:06:32 PDT 2004


[Sorry if this has been answered; I'm catching up on freebsd-questions
 and I haven't seen it in the next seven or eight digests.]

Tim Gustafson writes:

>I am getting the following error in "vi" pretty consistently:

>Error: input: Resource temporarily unavailable

>Usually I get this at every attempt I make to run vi.

Here's the scenario I found for this:

A threaded program (before 5.x and the new threading system) will turn
on Nonblocking on ALL the program's file descriptors, including stdin,
stdout, and stderr.  This setting is not on the process but on the open,
which is shared between processes (and thus, between various programs
that run at a given terminal, including the shell).  An unsophisticated,
innocent program will try to do a read(2) on the terminal, expecting to
block waiting for input.  Instead, it will receive an EAGAIN, which
basically means ``use poll(), select(), or kevent() to wait until the
input is _really_ there.''  So now vi/nvi has an input terminal that
doesn't behave like a terminal is supposed to behave; it's getting an
EAGAIN, and it does the safest thing it knows: it reports the problem
and goes away.

I use this little program to check for Nonblocking and restore the
normal (Blocking) state on the tty:

#include <iostream>
#include <fcntl.h>
#include <errno.h>
#include <string.h>


bool checkfd( int fd );

int
main()
{
        return checkfd( 0 )
            && checkfd( 1 )
            && checkfd( 2 ) ? 0 : 1;
}


bool
checkfd( int fd )
{
        int flags = fcntl( fd, F_GETFL, 0 );
        if( flags == -1 )
        {
                cerr << "Fd " << fd << ": " << strerror( errno ) << endl ;
                return false;
        }

        cout << fd << ( ( flags & O_NONBLOCK ) ? " nonblocking" : " blocking" )
                                                                << endl ;
        if( ! ( flags & O_NONBLOCK ) )
                cerr << "blocking" << endl ;
        else
        {
                cerr << "nonblocking" << endl ;
                if( fcntl( fd, F_SETFL, flags & ~O_NONBLOCK ) == -1 )
                {
                        cerr << "Couldn't set O_NONBLOCK: " << errno
                                        << " " << strerror( errno ) << endl ;
                        return false;
                }
        }

        return true;
}

Hope this helps.

    Mark Terribile



	
		
__________________________________
Do you Yahoo!?
Friends.  Fun.  Try the all-new Yahoo! Messenger.
http://messenger.yahoo.com/ 


More information about the freebsd-questions mailing list