Bug 23173

Summary: read hangs in linux emulation
Product: Base System Reporter: bbl <bbl>
Component: kernAssignee: Marcel Moolenaar <marcel>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.2-RELEASE   
Hardware: Any   
OS: Any   

Description bbl 2000-11-29 11:00:01 UTC
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");
}
Comment 1 bn 2001-04-29 03:36:05 UTC
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.
Comment 2 gte743n 2002-06-19 21:31:53 UTC
a patch has been given, can this pr be closed?

-- 
Holland King        
gte743n@cad.gatech.edu
Comment 3 gte743n 2002-11-19 04:48:10 UTC
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
Comment 4 Doug Barton freebsd_committer freebsd_triage 2003-01-23 10:17:45 UTC
State Changed
From-To: open->feedback


Is this still a problem with more modern systems?
Comment 5 Philipp Mergenthaler 2003-05-11 08:47:21 UTC
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;
 	}
Comment 6 Maxim Konovalov freebsd_committer freebsd_triage 2003-06-28 19:31:38 UTC
State Changed
From-To: feedback->open

Marcel, could your please take a look at the patch in the PR? 


Comment 7 Maxim Konovalov freebsd_committer freebsd_triage 2003-06-28 19:31:38 UTC
Responsible Changed
From-To: freebsd-bugs->marcel

Over to maintainer.
Comment 8 Marcel Moolenaar freebsd_committer freebsd_triage 2003-06-28 20:32:44 UTC
State Changed
From-To: open->closed

Patch committed to -current. MFC in 5 days. Sorry for the delay.