Bug 20251 - termio's ~ICANON causes read to return NUL for EOT sometimes
Summary: termio's ~ICANON causes read to return NUL for EOT sometimes
Status: CLOSED CURRENTRELEASE
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: kernel   
(Show other bugs)
Version: 8.0
Hardware: i686
OS: Linux
medium
medium
Target Milestone: ---
Assignee: Arjan van de Ven
QA Contact: Brian Brock
URL:
Whiteboard:
Keywords:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2000-11-02 21:02 UTC by Todd Allen
Modified: 2008-08-01 16:22 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2004-09-30 15:38:51 UTC
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

Description Todd Allen 2000-11-02 21:02:17 UTC
If I turn off ICANON via tcsetattr(), and then do several reads(), EOT
characters sometimes are turned into NUL's and sometimes remain EOT's.

Build the following program, and run it.  It expects input, will print
"EOF" for every EOT character, and will print the hex code for any other
character, including NUL as "00".  Then type control-D over and over again
real fast.  You'll see "00" sometimes and "EOF" sometimes.

I notice that, in n_tty.c, EOF_CHAR(tty) is mutated into __DISABLED_CHAR,
and I suspect it's something to do with that.  I'm guessing there's
supposed to be a place where that's undone and it's not working right with
ICANON turned off.  That's all I've been able to deduce.

Here's the source:

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <termios.h>

static int  fd       = 0;
static int  waiting  = 0;
static int  sleepily = 0;

main()
{
   for (;;) {
      int             eof_ch       = '\004'; /* EOT, a.k.a. ^D */
      char            c;
      int             got;
      struct termios  termios_rec;
      struct termios  otermios_rec;

      tcgetattr(fd, &termios_rec);
      memcpy(&otermios_rec, &termios_rec, sizeof(struct termios));

      eof_ch = termios_rec.c_cc[VEOF];

      termios_rec.c_lflag     &= ~ICANON;
      termios_rec.c_cc[VMIN]  =  waiting;
      termios_rec.c_cc[VTIME] =  0;
      tcsetattr(fd, TCSANOW, &termios_rec);

      do {
         got = read(fd, &c, 1);
         if (got == -1 && errno != EAGAIN && errno != EINTR) {
            printf("read() go boom; errno = %d\n", errno);
            exit(1);
         }
      } while (waiting && got <= 0);

      tcsetattr(fd, TCSANOW, &otermios_rec);

      if (got <= 0) {
         if (sleepily) {
            printf("!avail\n");
         }
      } else if (c == eof_ch) {
         printf("EOF\n");
      } else {
         printf("%02x\n", c);
      }

      if (sleepily) {
         sleep(1);
      }
   }
}

Comment 1 Alan Cox 2002-12-15 03:10:48 UTC
Confirmed in 8.0 but seems to be kernel not libc


Comment 2 Bugzilla owner 2004-09-30 15:38:51 UTC
Thanks for the bug report. However, Red Hat no longer maintains this version of
the product. Please upgrade to the latest version and open a new bug if the problem
persists.

The Fedora Legacy project (http://fedoralegacy.org/) maintains some older releases, 
and if you believe this bug is interesting to them, please report the problem in
the bug tracker at: http://bugzilla.fedora.us/



Note You need to log in before you can comment on or make changes to this bug.