Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Date: Thu, 6 Jun 2002 12:22:55 -0400 From: linguist-cygwin AT rich-paul DOT net To: cygwin AT cygwin DOT com Subject: Bug in poll/select from console only [w/test case] Message-ID: <20020606122255.A24137@monster.rich-paul.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.3.16i X-Operating-System: Linux monster 2.4.17-SMPs There appears to be a bug in the console reading machenery in the 2002-06-03 snapshot. The problem is that if you're sitting at the console and type a space bar, a process which is polling stdin will start getting read-ready returns. But if that process calls read() it will block until the enter key is pressed. The problem must be in peek_console, which looks to be in more than one way the wrong tool for the job: The bug I see is that it appears to assume that PeekConsoleInput implies that the file descriptor is ready to read. But that is after the check that fails with my test case: I do see the 'already ready' message from line 631. The code behind that is convoluted enough that I'd have to look at the whold f*h*_console object before I felt comfortable messing with it. Just for what it's worth, however, when I have written similar code in the past, I have always had a single routine that sucked data into a buffer somewhere and parsed it enough to know if it was ready to return at least one line. If there was a line already buffered, this routine would return immediately. I called this routine in my get method and also in my peek method, so peek would read the underlying device. It could be that grabbing a streambuffer object out of the iostreams library is just what the doctor ordered for this. Anyway, I'm sorry I don't have time to fix this, but my company is releasing a new version of it's product this week, and would be grumpy if their lead programmer was off playing in somebody elses source. If it's still there next week I'll have a better look. Sadly, the following test case, due to the nature of the bug, requires a monkey to press the button, if you know a way to automate it, let me know. Success is measured by seeing read() return immediately alter poll() does. Oh ... be sure to redirect either out or error to a file, or the double output will be really annoying. -- poll.1 -- Usage: g++ -opoll.exe poll.cxx 2>/dev/null ./poll and rejoice when you don't see the poll() return until you hit enter. -- poll.cxx -- #include #include #include #include #include #include int start_time=time(0); void write_str(const char*msg, int fd = 1) { //FIXME write(1, msg, strlen(msg)); write(2, msg, strlen(msg)); } void write_num(int val, int fd = 1) { char buffer[10]; sprintf(buffer,"%d%c", val, 0); write_str(buffer,fd); } void nl(int fd = 1){ write_str("\n"); } void write_err(const char *fn, int fd = 2) { write_str(fn, fd); write_str(":", fd); write_str(strerror(errno), fd); } void start(){ char buffer[20]; sprintf(buffer,"in: %d\n%c", (time(0)-start_time) , 0); write_str(buffer); start_time = time(0); }; void finish() { char buffer[20]; sprintf(buffer,"out: %d\n%c", (time(0)-start_time) , 0); write_str(buffer); start_time = time(0); } int report(const char *fn, int res) { char buffer[20]; sprintf(buffer,"%s: %d\n%c", fn,res , 0); write_str(buffer); if ( res < 0 ) { write_err(fn); } return res; } int main ( int, char** ) { pollfd sin; sin.events=POLLIN; sin.fd=0; for(;;){ sin.revents=0; errno=0; nl(); start(); int res = report("poll", poll(&sin,1,1000)); finish(); int err = errno; if ( res < 0 ) write_err("read"); bool done = false; bool ready = false; switch(sin.revents){ case POLLIN: write_str("POLLIN\n"); ready=true; case 0: //fallthrough done = false ; break; case POLLOUT: write_str("POLLOUT\n"); break; case POLLERR: write_str("POLLERR\n"); break; case POLLHUP: write_str("POLLHUP\n"); break; case POLLNVAL: write_str("POLLNVAL\n"); break; } if ( done ) break; if ( !ready ) continue; char buf[1024]; nl(); start(); res = report("read", read(0,buf, sizeof(buf))); finish(); if ( res > 0 ) continue; if ( res < 0 ) write_err("read"); exit(res<0); } write_str("done\n"); } -- Got freedom? Vote Libertarian: http://www.lp.org -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/