Please clarify what happens when doing the following with fcntl and open - Unix

This is a discussion on Please clarify what happens when doing the following with fcntl and open - Unix ; Hi, I'm trying to weed out some problems in the code I'm writing for a serial application. I'm using the POSIX termios structures for this program (although, not much that I'm about to ask will directly reference this). The first ...

+ Reply to Thread
Results 1 to 5 of 5

Thread: Please clarify what happens when doing the following with fcntl and open

  1. Please clarify what happens when doing the following with fcntl and open

    Hi,

    I'm trying to weed out some problems in the code I'm writing for a
    serial application. I'm using the POSIX termios structures for this
    program (although, not much that I'm about to ask will directly
    reference this).

    The first and most important question, I think, is do the functions
    open, specifically the flags argument not anything else, and the fcntl
    function operate on the same data structures describing the file
    descriptor? The reason I ask is as follows:

    in my code I have this

    fd = open( dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );

    // then later on, but still in the ctor for this class
    if( fcntl( fd, F_SETFL, 0 ) < 0 ) {
    // throw an error saying what happened
    }

    Does this call to fcntl stomp all I did in the open call? Basically,
    on the reading end, I'm always setting VTIME to 0 and VMIN to a non-
    zero value because I want to wait for a specific amount of data to be
    available. Setting the no-delay (O_NDELAY) flag would seem to negate
    this. Therefore, I clear the flags, but does the call to fcntl stomp
    everything else too?

    Reading the manual pages would seem to indicate that part of this
    structure is not accessible to fcntl. To be sure, I looked in /usr/
    include/bits/fcntl.h (for Linux) and found the following comments next
    to the constants like O_NOCTTY, /* not fcntl */. This would seem to
    further the idea that, if the two functions manipulate a common data
    structure, they do not overlap 100%. Is this true?

    On a different note, What approaches would be good for constructing a
    timeout mechanism for waiting for data on the reading end? The
    program operates in two modes; a standard mode and a flood mode. In
    standard, the flow of data is bidirectional, but is unidirectional in
    the other. In flood mode, I want the program to timeout if no data
    ever arrives. If my understanding of the VMIN member to the c_cc
    array is correct, this is only an inter-byte timer meaning that it
    only works once data has begun to be received. What if data never
    comes?

    Andy


  2. Re: Please clarify what happens when doing the following with fcntl and open

    2007-04-17, 12:56(-07), Andrew Falanga:
    [...]
    > fd = open( dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );
    >
    > // then later on, but still in the ctor for this class
    > if( fcntl( fd, F_SETFL, 0 ) < 0 ) {
    > // throw an error saying what happened
    > }
    >
    > Does this call to fcntl stomp all I did in the open call? Basically,
    > on the reading end, I'm always setting VTIME to 0 and VMIN to a non-
    > zero value because I want to wait for a specific amount of data to be
    > available. Setting the no-delay (O_NDELAY) flag would seem to negate
    > this. Therefore, I clear the flags, but does the call to fcntl stomp
    > everything else too?


    There's an answer to your question in my man page of fcntl on
    Linux:

    On Linux this command can only change the O_APPEND, O_ASYNC,
    O_DIRECT, O_NOATIME, and O_NONBLOCK flags.

    (O_NONBLOCK being the same as O_NDELAY),

    So fcntl(F_SETFL, 0) will only clear O_NDELAY in your case.

    > On a different note, What approaches would be good for constructing a
    > timeout mechanism for waiting for data on the reading end? The
    > program operates in two modes; a standard mode and a flood mode. In
    > standard, the flow of data is bidirectional, but is unidirectional in
    > the other. In flood mode, I want the program to timeout if no data
    > ever arrives. If my understanding of the VMIN member to the c_cc
    > array is correct, this is only an inter-byte timer meaning that it
    > only works once data has begun to be received. What if data never
    > comes?

    [...]

    The VMIN/VTIME stuff are for ioctls to the terminal driver, so
    that's one layer underneath the fcntl.

    Basically, if you do a TCSETSW ioctl with VMIN=2 and VTIME=0
    (with ~ICANON), the terminal driver will not make anything
    available to any read() until 2 characters are coming from the
    line.

    So, with O_NDELAY, a read() will block until 2 characters are
    received, and with O_NDELAY a read will return -1 (EAGAIN) until
    2 characters are received

    With VMIN=10 VTIME=10 ~ICANON (again, that's only for terminal
    devices) there'll be nothing to be read (so read() will block or
    will return -1 EAGAIN depenind on O_NDELAY) until either 10
    characters have been received, or at least one character has
    been received and no character have been received in the past 10
    ds (1 s).

    If you want a timeout on a read, best is probably to use poll()
    or select(), the tcsetattr will only work on terminals.

    --
    Stéphane

  3. Re: Please clarify what happens when doing the following with fcntl and open

    On Apr 17, 2:26 pm, Stephane CHAZELAS wrote:
    > 2007-04-17, 12:56(-07), Andrew Falanga:
    > [...]
    >
    > > fd = open( dev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY );

    >
    > > // then later on, but still in the ctor for this class
    > > if( fcntl( fd, F_SETFL, 0 ) < 0 ) {
    > > // throw an error saying what happened
    > > }

    >
    > > Does this call to fcntl stomp all I did in the open call? Basically,
    > > on the reading end, I'm always setting VTIME to 0 and VMIN to a non-
    > > zero value because I want to wait for a specific amount of data to be
    > > available. Setting the no-delay (O_NDELAY) flag would seem to negate
    > > this. Therefore, I clear the flags, but does the call to fcntl stomp
    > > everything else too?

    >
    > There's an answer to your question in my man page of fcntl on
    > Linux:
    >
    > On Linux this command can only change the O_APPEND, O_ASYNC,
    > O_DIRECT, O_NOATIME, and O_NONBLOCK flags.
    >
    > (O_NONBLOCK being the same as O_NDELAY),
    >
    > So fcntl(F_SETFL, 0) will only clear O_NDELAY in your case.
    >
    > > On a different note, What approaches would be good for constructing a
    > > timeout mechanism for waiting for data on the reading end? The
    > > program operates in two modes; a standard mode and a flood mode. In
    > > standard, the flow of data is bidirectional, but is unidirectional in
    > > the other. In flood mode, I want the program to timeout if no data
    > > ever arrives. If my understanding of the VMIN member to the c_cc
    > > array is correct, this is only an inter-byte timer meaning that it
    > > only works once data has begun to be received. What if data never
    > > comes?

    >
    > [...]
    >
    > The VMIN/VTIME stuff are for ioctls to the terminal driver, so
    > that's one layer underneath the fcntl.
    >
    > Basically, if you do a TCSETSW ioctl with VMIN=2 and VTIME=0
    > (with ~ICANON), the terminal driver will not make anything
    > available to any read() until 2 characters are coming from the
    > line.
    >
    > So, with O_NDELAY, a read() will block until 2 characters are
    > received, and with O_NDELAY a read will return -1 (EAGAIN) until
    > 2 characters are received
    >


    With which one did you mean without O_NDELAY?

    Andy


  4. Re: Please clarify what happens when doing the following with fcntl and open

    2007-04-17, 13:34(-07), Andrew Falanga:
    [...]
    >> (O_NONBLOCK being the same as O_NDELAY),

    [...]
    >> So, with O_NDELAY, a read() will block until 2 characters are
    >> received, and with O_NDELAY a read will return -1 (EAGAIN) until
    >> 2 characters are received
    >>

    >
    > With which one did you mean without O_NDELAY?

    [...]

    Well, the O_NONBLOCK gives some kind of a hint doesn't it?

    Note that EAGAIN can sometimes be EWOULDBLOCK, though on Linux,
    they are generally the same.

    --
    Stéphane

  5. Re: Please clarify what happens when doing the following with fcntl and open

    2007-04-17, 13:34(-07), Andrew Falanga:
    [...]
    >> Basically, if you do a TCSETSW ioctl with VMIN=2 and VTIME=0
    >> (with ~ICANON), the terminal driver will not make anything
    >> available to any read() until 2 characters are coming from the
    >> line.
    >>
    >> So, without O_NDELAY, a read() will block until 2 characters are
    >> received, and with O_NDELAY a read will return -1 (EAGAIN) until
    >> 2 characters are received

    [...]

    Sorry, I was wrong.

    Though that's true on Solaris or HPUX at least, it is not on
    Linux. There, the O_NDELAY causes characters to be delivered as
    soon as they arrive whatever the value of VMIN, see:

    stty min 10 time 0 -icanon; strace -e read perl -MFcntl -e '
    fcntl(STDIN, F_SETFL, O_NONBLOCK | fcntl(STDIN, F_GETFL, 0));
    while ($_ = <> || $!{EAGAIN}) {sleep(1)}'

    min 10 would mean that you need to enter 10 characters before
    read() (<>) gets anything, but running that command shows that
    as soon as you type even only one, it is available to the next
    read.

    Wonder if that could be considered as a bug in Linux.

    --
    Stéphane

+ Reply to Thread