[Win32utils-devel] rb_w32_select function patch
Heesob Park
phasis at gmail.com
Tue Apr 29 05:32:48 EDT 2008
Hi,
2008/4/29 Luis Lavena <luislavena at gmail.com>:
> On Tue, Apr 29, 2008 at 2:53 AM, Heesob Park <phasis at gmail.com> wrote:
> > Hi,
> >
> > [snip]
>
> > I added some safe check code.
> > Here is diff -u output:
> >
>
> Hello Park,
>
> I just tested your patch for rb_w32_select and found, even gets() is
> no longer blocking other threads from being executed, everything stops
> when you start typing something...
>
> Compared to other other platforms, the behavior differs, so maybe is
> not the best solution...
>
> I thought your previous patch (2005, 2006 maybe?) workaround that
> issue. But don't remember quite right.
>
That patch is not working well as you expected.
> In any case, this looks good, one step closer :-)
>
> (btw, platform i386-mingw32)
>
Here is a modified version for two step closer :)
--- win32.c.org 2008-04-29 14:44:41.000000000 +0900
+++ win32.c 2008-04-29 18:25:26.000000000 +0900
@@ -2046,6 +2046,65 @@
return fileset->fd_count;
}
+static HANDLE main_select_event=NULL;
+static HANDLE *select_thread_list=NULL;
+
+static DWORD WINAPI
+select_read_thread(PVOID argp)
+{
+ HANDLE fd_handle = (HANDLE)argp;
+ DWORD ret = 1;
+ DWORD mode = 0;
+
+ GetConsoleMode(fd_handle,&mode);
+ if(mode!=0) {
+ // RealConsole Input
+ DWORD num_events,num_events_read,pre_num=0;
+ INPUT_RECORD *input_record;
+ int i;
+
+ while(1) {
+ if(WaitForSingleObject(main_select_event,0)!=WAIT_TIMEOUT) break;
+ GetNumberOfConsoleInputEvents(fd_handle, &num_events);
+ if(pre_num != num_events) {
+ input_record = (INPUT_RECORD
*)malloc(sizeof(INPUT_RECORD)*num_events);
+ PeekConsoleInput(fd_handle, input_record, num_events,
&num_events_read);
+ for(i=0;i<num_events;i++) {
+ if ((input_record[i].EventType == KEY_EVENT) &&
input_record[i].Event.KeyEvent.bKeyDown) {
+ if(input_record[i].Event.KeyEvent.uChar.AsciiChar==13) { /*
carriage return */
+ free(input_record);
+ return ret;
+ }
+ else if(input_record[i].Event.KeyEvent.uChar.AsciiChar==26) { /*
^Z - end of file */
+ free(input_record);
+ return ret;
+ }
+ }
+ }
+ free(input_record);
+ pre_num = num_events;
+ }
+ }
+ return ret;
+ }
+ return ret;
+}
+
+static DWORD WINAPI
+select_write_thread(PVOID argp)
+{
+ HANDLE fd_handle = (HANDLE)argp;
+ DWORD ret = 1;
+ DWORD mode = 0;
+
+ GetConsoleMode(fd_handle,&mode);
+ if(mode!=0) {
+ // RealConsole Output
+ return ret;
+ }
+ return ret;
+}
+
long
rb_w32_select (int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
struct timeval *timeout)
@@ -2057,6 +2116,10 @@
fd_set trap;
#endif /* USE_INTERRUPT_WINSOCK */
int file_nfds;
+ DWORD val;
+ int fd;
+ int i;
+ DWORD exit_code;
if (!NtSocketsInitialized) {
StartSockets();
@@ -2074,6 +2137,57 @@
file_nfds += extract_file_fd(wr, &file_wr);
if (file_nfds)
{
+ main_select_event = CreateEvent(NULL,TRUE,FALSE,"main_select_event");
+ if(main_select_event == NULL)
+ {
+ fprintf(stderr,"CreateEvent failed (%d)\n", GetLastError());
+ return -1;
+ }
+ select_thread_list = malloc(sizeof(HANDLE)*(file_nfds+1));
+
+ for(i=0; i<file_nfds; i++)
+ {
+ if(i<file_rd.fd_count) {
+ select_thread_list[i] = CreateThread(NULL,0,select_read_thread,
+ (PVOID)file_rd.fd_array[i],0,&val);
+ }
+ else {
+ select_thread_list[i] = CreateThread(NULL,0,select_write_thread,
+ (PVOID)file_wr.fd_array[i-file_rd.fd_count],0,&val);
+ }
+ if (select_thread_list[i] == NULL)
+ {
+ printf("CreateThread failed (%d)\n", GetLastError());
+ return -1;
+ }
+ }
+
+ select_thread_list[file_nfds] = interrupted_event;
+ if(timeout)
+ r = WaitForMultipleObjects(file_nfds+1,select_thread_list,FALSE,
+ timeout->tv_sec * 1000 + timeout->tv_usec / 1000);
+ else
+ r =
WaitForMultipleObjects(file_nfds+1,select_thread_list,FALSE,INFINITE);
+ if (!SetEvent(main_select_event) )
+ {
+ printf("SetEvent failed (%d)\n", GetLastError());
+ return -1;
+ }
+ for(i=0;i<file_nfds;i++) {
+ while(1) {
+ exit_code = 0;
+ GetExitCodeThread(select_thread_list[i],&exit_code);
+ if(exit_code!=STILL_ACTIVE) {
+ CloseHandle(select_thread_list[i]);
+ break;
+ }
+ }
+ }
+ CloseHandle(main_select_event);
+ free(select_thread_list);
+ if(r==WAIT_TIMEOUT||r==file_nfds)
+ return 0;
+
// assume normal files are always readable/writable
// fake read/write fd_set and return value
if (rd) *rd = file_rd;
Regards,
Park Heesob
More information about the win32utils-devel
mailing list