Bug 20490

Summary: Termios timeout parameters, VMIN, VTIME, dont work with lang/python
Product: Base System Reporter: r_chipi <r_chipi>
Component: threadsAssignee: freebsd-threads (Nobody) <threads>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.1-RELEASE   
Hardware: Any   
OS: Any   

Description r_chipi 2000-08-08 22:20:00 UTC
When using VMIN = 0 and VTIME > 0 to control receiver timeout
in Python, it does not work as it should.  For example, programming
VMIN = 0 and VTIME = 200 should make a read block for at least 20 seconds
or until a character is received, however, the read does not block and
returns immediately.  When a similar routine is written in C it works
as it should.

How-To-Repeat: To reapeat write the following test code:

# This code does not work

import os
from TERMIOS import *
from tty import *

fd = os.open("/dev/cuaa1", os.O_RDWR)
attrs = tcgetattr(fd)
attrs[CFLAG] = CS8 | CLOCAL | CREAD
attrs[OFLAG] = attrs[OFLAG] & ~OPOST
attrs[LFLAG] = 0
attrs[CC][VMIN] = 0
attrs[CC][VTIME] = 200
tcsetattr(fd, TCSANOW, attrs)


print os.read(fd, 80)

/* the equivalent test in C works as it should */
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>


main()
{
    struct termios term;
    int fd, bytes;
    char buf[80];

    fd = open("/dev/cuaa1", O_RDWR);
    if (fd < 0)
    {
        perror("open");
        return 1;
    }

    tcgetattr(fd, &term);
    term.c_cflag = CS8 | CREAD | CLOCAL;
    term.c_oflag &= ~OPOST;
    term.c_lflag = 0;
    term.c_cc[VMIN] = 0;
    term.c_cc[VTIME] = 200;
    tcsetattr(fd, TCSANOW, &term);

    bytes = read(fd, buf, 40);
    buf[bytes] = 0;
    puts(buf);
    return 0;

}
Comment 1 Thomas Gellekum 2000-08-14 12:26:31 UTC
r_chipi@yahoo.com writes:

> /* the equivalent test in C works as it should */

It doesn't if you link against libc_r (`cc ttt.c -o ttt -pthread');
same failure as with the python version. I have yet to look at the
code in libc_r, though.

tg
Comment 2 deischen 2000-08-14 22:13:39 UTC
I don't think this is a libc_r problem.  The threads library sets
all file descriptors to non-blocking and uses poll() to determine
when data is ready.  But before poll()ing, the threads library
performs a read() on the non-blocking socket.  It expects the
return value to be -1 with errno set to EAGAIN if there is no
data ready.  If you set the file to non-blocking in the example
provided, read() returns 0 instead of -1.

Another problem to arise, even if this is fixed, is that our
current threads library knows nothing of VMIN/VTIME and tcsetattr().
Since the file descriptor is non-blocking, the timer will not
be effective, and the expected 20 second timeout will not occur.
I'd expect the example program to block indefinitely until the
requested (40 bytes of) data arrives.  This will work correctly
when we get scheduler activations.  I don't think it is worth the
time or effort to get the threads library to wrap tcsetattr() and
emulate the effects of VMIN/VTIME.  If you want this to work with
our current threads library, I would suggest recoding it to use
select() or poll() to give you the needed timeout (and not use
VMIN/VTIME).

Here's the modified example:

#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>

#include <assert.h>
#include <errno.h>

main()
{
    struct termios term;
    int fd, bytes, flags;
    char buf[80];

    fd = open("/dev/cuaa1", O_RDWR);
    if (fd < 0)
    {
	perror("open");
	return 1;
    }

    tcgetattr(fd, &term);
    term.c_cflag = CS8 | CREAD | CLOCAL;
    term.c_oflag &= ~OPOST;
    term.c_lflag = 0;
    term.c_cc[VMIN] = 0;
    term.c_cc[VTIME] = 200;
    tcsetattr(fd, TCSANOW, &term);

    assert((flags = fcntl(fd, F_GETFL, 0)) != -1);
    assert(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);

    bytes = read(fd, buf, 40);
    printf("Read returned %d, errno = %d\n", bytes, errno);
    buf[bytes] = 0;
    puts(buf);
    return 0;
}

--
Dan Eischen
Comment 3 Ade Lovett freebsd_committer freebsd_triage 2000-09-18 21:28:33 UTC
Responsible Changed
From-To: freebsd-ports->tg

Over to maintainer to decide what to do with this.
Comment 4 Mark Linimon freebsd_committer freebsd_triage 2003-11-07 07:51:39 UTC
Responsible Changed
From-To: tg->perky

Over to current maintainer of Python (for the last year or so) 
to see if this stale PR is still relevant.
Comment 5 Florent Thoumie freebsd_committer freebsd_triage 2005-04-13 11:45:46 UTC
	From what I'm reading in the audit trail, this is neither an
	issue concerning the FreeBSD port, nor a python problem.

	I think this should be relocated to bin or threads.

-- 
Florent Thoumie
flz@FreeBSD.org
Comment 6 Ceri Davies freebsd_committer freebsd_triage 2005-06-06 22:29:37 UTC
Responsible Changed
From-To: perky->freebsd-threads

Seems to be a thread library problem.
Comment 7 Ceri Davies freebsd_committer freebsd_triage 2005-06-18 20:56:25 UTC
State Changed
From-To: open->closed

Sounds fair to me.