| Summary: | Termios timeout parameters, VMIN, VTIME, dont work with lang/python | ||
|---|---|---|---|
| Product: | Base System | Reporter: | r_chipi <r_chipi> |
| Component: | threads | Assignee: | freebsd-threads (Nobody) <threads> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.1-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
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 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
Responsible Changed From-To: freebsd-ports->tg Over to maintainer to decide what to do with this. 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. 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 Responsible Changed From-To: perky->freebsd-threads Seems to be a thread library problem. State Changed From-To: open->closed Sounds fair to me. |
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; }