This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] patch for run.exe -- ATTN: ago


As detailed here:
http://cygwin.com/ml/cygwin/2006-05/msg00471.html

run.exe currently launches clients without any stdio handles and without any console at all. That's over-ambitious: what run REALLY should do is launch the client with a *hidden* console and *working* stdio handles.

Run is a console-hider, not a daemonizer -- and some apps (like, err, rxvt-unicode), even tho they are GUIs, don't behave well when launched without working stdio (even if those handles point to an invisible console, and really shouldn't be used by the app anyway!)

The attached patch adapts code from cygwin's fhandler_init, using NT/2K/XP-only APIs to enable AllocConsole() to initialize the stdio handles *without* that console ever becoming visible, not even for a brief flash. Because these APIs are only available on some of the supported OSes, I use LoadLibrary/GetProcAddress and function pointers, so that on the older OSes the behavior should be unchanged from 1.1.9-1.

With this patch, rxvt-unicode-X is happy and no longer sucks 100% CPU when launched by run.exe with loginShell=true, as is the case with run-1.1.9-1. (At least, on NT/2K/XP. On 95/98/Me, I expect rxvt-unicode-X will be just as unhappy with this patch as without. Half loaves and baby steps...)

--
Chuck
diff -urN -x .build -x .inst -x .sinst -x .buildlogs run-1.1.9-orig/src/run.c run-1.1.9/src/run.c
--- run-1.1.9-orig/src/run.c	2006-04-06 14:10:55.000000000 -0400
+++ run-1.1.9/src/run.c	2006-05-18 01:50:43.859375000 -0400
@@ -32,6 +32,7 @@
 #define WIN32
 
 #include <windows.h>
+#include <winuser.h>
 #include <string.h>
 #include <malloc.h>
 #include <stdlib.h>
@@ -193,6 +194,67 @@
         free(var);
     }
 }
+BOOL setup_invisible_console()
+{
+   HWINSTA h, horig;
+   USEROBJECTFLAGS oi;
+   DWORD len;
+   BOOL b = FALSE; 
+   HMODULE lib = NULL;
+   HWINSTA WINAPI (*GetProcessWindowStationFP)(void) = NULL;
+   BOOL WINAPI (*GetUserObjectInformationFP)(HANDLE, int, PVOID, DWORD, PDWORD) = NULL;
+   HWINSTA WINAPI (*CreateWindowStationFP)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES) = NULL;
+   BOOL WINAPI (*SetProcessWindowStationFP)(HWINSTA) = NULL;
+   BOOL WINAPI (*CloseWindowStationFP)(HWINSTA) = NULL;
+
+   /* First, set up function pointers */
+   if (lib = LoadLibrary ("user32.dll"))
+   {
+       GetProcessWindowStationFP = (HWINSTA WINAPI (*)(void))
+           GetProcAddress (lib, "GetProcessWindowStation");
+       GetUserObjectInformationFP = (BOOL WINAPI (*)(HANDLE, int, PVOID, DWORD, PDWORD))
+           GetProcAddress (lib, "GetUserObjectInformationW"); /* ugly! */
+       CreateWindowStationFP = (HWINSTA WINAPI (*)(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES))
+           GetProcAddress (lib, "CreateWindowStationW"); /* ugly */
+       SetProcessWindowStationFP = (BOOL WINAPI (*)(HWINSTA))
+           GetProcAddress (lib, "SetProcessWindowStation");
+       CloseWindowStationFP = (BOOL WINAPI (*)(HWINSTA))
+           GetProcAddress (lib, "CloseWindowStation");
+
+       if (GetProcessWindowStationFP && 
+            GetUserObjectInformationFP &&
+            CreateWindowStationFP &&
+            SetProcessWindowStationFP &&
+            CloseWindowStationFP)
+       {
+           /* Then, do the work */
+           FreeConsole();
+           h = horig = (*GetProcessWindowStationFP)();
+           if (!horig 
+               || !(*GetUserObjectInformationFP) (horig, UOI_FLAGS, &oi, sizeof (oi), &len )
+               || !(oi.dwFlags & WSF_VISIBLE))
+           {
+               b = AllocConsole();
+           }
+           else
+           {
+               h = (*CreateWindowStationFP) (NULL, 0, STANDARD_RIGHTS_READ, NULL);
+               if (h)
+               {
+                   b = (*SetProcessWindowStationFP) (h);
+               }
+               b = AllocConsole();
+               if (horig && h && h != horig && (*SetProcessWindowStationFP) (horig))
+               {
+                   (*CloseWindowStationFP) (h);
+               }
+           }
+           return b;
+       }
+   }
+   /* otherwise, fail */ 
+   return FALSE;
+}
 
 int start_child(char* cmdline, int wait_for_child)
 {
@@ -204,6 +266,8 @@
 
    setup_win_environ();
 
+   setup_invisible_console();
+
    memset (&start, 0, sizeof (start));
    start.cb = sizeof (start);
    start.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]