[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v2] implement full-blown select(2) for winsock
From: |
Bruno Haible |
Subject: |
Re: [PATCH v2] implement full-blown select(2) for winsock |
Date: |
Mon, 29 Sep 2008 19:49:00 +0200 |
User-agent: |
KMail/1.5.4 |
> handle console handles (e.g. stdin)
For reference, here is the code that is in use in clisp to detect whether
reading from a handle would hang or return immediately. The deal with
ENABLE_LINE_INPUT is that PeekConsoleInput will say "yes there is something
is available" as soon as the user has started typing a line, but ReadFile
will hang until the user presses Return.
/* Determines whether ReadFile() on a file/pipe/console handle will hang.
Returns 0 for yes, 1 for no (or 2 for known EOF or 3 for available byte),
-1 for unknown. */
int fd_read_wont_hang_p (HANDLE fd)
{
/* This is pretty complex. To test this, create a file "listen.lisp"
containing the code
(tagbody 1 (prin1 (listen *terminal-io*)) (sys::%sleep 0 500) (go 1))
and execute "lisp.exe -q -i listen.lisp" with redirected standard input. */
switch (GetFileType(fd)) {
case FILE_TYPE_CHAR:
{
DWORD nevents;
if (GetNumberOfConsoleInputEvents(fd,&nevents)) { /* It's a console. */
if (nevents==0)
return 0;
INPUT_RECORD* events =
(INPUT_RECORD*)alloca(nevents*sizeof(INPUT_RECORD));
DWORD nevents_read;
DWORD mode;
if (!PeekConsoleInput(fd,events,nevents,&nevents_read)) {
OS_error();
}
if (nevents_read==0)
return 0;
if (!GetConsoleMode(fd,&mode)) {
OS_error();
}
if (mode & ENABLE_LINE_INPUT) {
/* Look out for a Key-Down event corresponding to CR/LF. */
DWORD i;
for (i = 0; i < nevents_read; i++) {
if (events[i].EventType == KEY_EVENT
&& events[i].Event.KeyEvent.bKeyDown
&& events[i].Event.KeyEvent.uAsciiChar == CR)
/* probably a byte available (except if it is Ctrl-Z) */
return -1;
}
} else { /* Look out for any Key-Down event. */
DWORD i;
for (i = 0; i < nevents_read; i++) {
if (events[i].EventType == KEY_EVENT
&& events[i].Event.KeyEvent.bKeyDown
&& events[i].Event.KeyEvent.uAsciiChar != 0)
/* probably a byte available (except if it is Ctrl-Z) */
return -1;
}
}
return 0;
} else if (!(GetLastError()==ERROR_INVALID_HANDLE)) {
OS_error();
}
}
/* Not a console. */
switch (WaitForSingleObject(fd,0)) {
case WAIT_OBJECT_0: /* a byte is available, or EOF */
return 1;
case WAIT_TIMEOUT:
return 0;
default:
OS_error();
}
case FILE_TYPE_DISK:
return 1;
case FILE_TYPE_PIPE:
{
DWORD nbytes;
if (PeekNamedPipe(fd,NULL,0,NULL,&nbytes,NULL)) { /* input pipe */
if (nbytes > 0)
return 3;
else
return 0;
} else if (GetLastError()==ERROR_BROKEN_PIPE) { /* EOF reached */
return 2;
} else if (GetLastError()==ERROR_ACCESS_DENIED) { /* output pipe */
/* => fake EOF. */
return 2;
} else {
OS_error();
}
}
default: /* It's a file (or something unknown). */
return -1;
}
}
Re: [PATCH v2] implement full-blown select(2) for winsock, Bruno Haible, 2008/09/28
Re: [PATCH v2] implement full-blown select(2) for winsock, Bruno Haible, 2008/09/29
Re: [PATCH v2] implement full-blown select(2) for winsock, Bruno Haible, 2008/09/29