[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