Mail Archives: cygwin/2002/06/06/12:39:14
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. <G> 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
<space>
and rejoice when you don't see the poll() return until you hit
enter.
--
poll.cxx
--
#include <sys/poll.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
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/
- Raw text -