| Summary: | read hangs in linux emulation | ||
|---|---|---|---|
| Product: | Base System | Reporter: | bbl <bbl> |
| Component: | kern | Assignee: | Marcel Moolenaar <marcel> |
| Status: | Closed FIXED | ||
| Severity: | Affects Only Me | ||
| Priority: | Normal | ||
| Version: | 4.2-RELEASE | ||
| Hardware: | Any | ||
| OS: | Any | ||
Hi Bjarne.
There's a bug in the termios struct conversion, which replaces
0 in VMIN and VTIME by 255 (as it substitutes all _POSIX_VDISABLE from
Linux (0) by _POSIX_VDISABLE from FreeBSD (255) in termios.c_cc[]).
The following patch for /usr/src/sys/compat/linux/linux_ioctl.c will fix
this problem:
*** linux_ioctl.c.orig Sat Apr 28 03:08:21 2001
--- linux_ioctl.c Sun Apr 29 04:22:10 2001
***************
*** 321,327 ****
lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
for (i=0; i<LINUX_NCCS; i++) {
! if (lios->c_cc[i] == _POSIX_VDISABLE)
lios->c_cc[i] = LINUX_POSIX_VDISABLE;
}
lios->c_line = 0;
--- 321,328 ----
lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
for (i=0; i<LINUX_NCCS; i++) {
! if (i != LINUX_VMIN && i != LINUX_VTIME &&
! lios->c_cc[i] == _POSIX_VDISABLE)
lios->c_cc[i] = LINUX_POSIX_VDISABLE;
}
lios->c_line = 0;
***************
*** 454,460 ****
bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
for (i=0; i<NCCS; i++) {
! if (bios->c_cc[i] == LINUX_POSIX_VDISABLE)
bios->c_cc[i] = _POSIX_VDISABLE;
}
--- 455,462 ----
bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
for (i=0; i<NCCS; i++) {
! if (i != VMIN && i != VTIME &&
! bios->c_cc[i] == LINUX_POSIX_VDISABLE)
bios->c_cc[i] = _POSIX_VDISABLE;
}
Greetings,
Boris Nikolaus
P.S.: Your test program is missing a "st_tbuf = old_st;" after the tcgetattr.
a patch has been given, can this pr be closed? -- Holland King gte743n@cad.gatech.edu this bug has had a patch for close to 9 months now, and no other traffic. any reason it has not been closed? -- Holland King gte743n@cad.gatech.edu State Changed From-To: open->feedback Is this still a problem with more modern systems? I can confirm that this bug still exists in -current as of 2003-05-11
and that the patch by Boris Nikolaus fixes it.
It doesn't apply cleanly to -current anymore, though. Below is an
updated version.
Bye, Philipp
Index: linux_ioctl.c
===================================================================
RCS file: /ncvs/src/sys/compat/linux/linux_ioctl.c,v
retrieving revision 1.107
diff -u -r1.107 linux_ioctl.c
--- linux_ioctl.c 24 Apr 2003 23:36:35 -0000 1.107
+++ linux_ioctl.c 11 May 2003 07:06:50 -0000
@@ -345,7 +345,8 @@
lios->c_cc[LINUX_VLNEXT] = bios->c_cc[VLNEXT];
for (i=0; i<LINUX_NCCS; i++) {
- if (lios->c_cc[i] == _POSIX_VDISABLE)
+ if (i != LINUX_VMIN && i != LINUX_VTIME &&
+ lios->c_cc[i] == _POSIX_VDISABLE)
lios->c_cc[i] = LINUX_POSIX_VDISABLE;
}
lios->c_line = 0;
@@ -484,7 +485,8 @@
bios->c_cc[VLNEXT] = lios->c_cc[LINUX_VLNEXT];
for (i=0; i<NCCS; i++) {
- if (bios->c_cc[i] == LINUX_POSIX_VDISABLE)
+ if (i != VMIN && i != VTIME &&
+ bios->c_cc[i] == LINUX_POSIX_VDISABLE)
bios->c_cc[i] = _POSIX_VDISABLE;
}
State Changed From-To: feedback->open Marcel, could your please take a look at the patch in the PR? Responsible Changed From-To: freebsd-bugs->marcel Over to maintainer. State Changed From-To: open->closed Patch committed to -current. MFC in 5 days. Sorry for the delay. |
The following testprogram wil demonstrate an error in linux compatibility between linux and freebsd, both on intelplatform. The program is compiled on an intel linux Slackware 7.0 with gcc 2.95.2 and the binary is then copied to FreeBSD 4.2-stable. The problem is seen both on 4.1 and 4.2 The correct behaviour on linux, is to read a charcter on stdin, provided there is one, othervise return 0. On FreeBSD, the read will just hang until a key is pressed. After a key is pressed, the character is returned after aprox. 20 seconds. If st_tbuf.c_cc[VTIME] = 0; is changed to st_tbuf.c_cc[VTIME] = 100; the read is supposed to wait max. 10 seconds, whereafter 0 is returned. On FreeBSD, read will hang indefinitely, until a key is pressed. After a key is pressed, read will return after aprox. 20 seconds. How-To-Repeat: #include <stdio.h> #include <termios.h> #include <unistd.h> struct termios st_tbuf, old_st; main () { char buf [256]; int ret; ret = tcgetattr(0, &old_st); st_tbuf.c_lflag &= ~(ICANON | ECHO); st_tbuf.c_cc[VMIN] = 0; st_tbuf.c_cc[VTIME] = 0; ret = tcsetattr(0, TCSANOW, &st_tbuf); ret = read (0, (char *)buf, 1); tcsetattr(0, TCSANOW, &old_st); if (ret > 0) printf ("inp = %c\n", buf[0]); else printf ("Zip\n"); }