[PATCH 2/2] kernelbase: Add support for CREATE_NO_WINDOW flag.

Eric Pouech eric.pouech at orange.fr
Wed Apr 6 04:57:27 CDT 2022


Le 06/04/2022 à 08:34, Eric Pouech a écrit :
>>
>>> this 'next' - aka third - patch,  just creates a window less console 
>>> in some cases for an initial process and should fix (or at least 
>>> improve) a couple of open bugs
>>>
>>> (to make it short, in scenario like "wine foo >& log < /dev/null", 
>>> it prevents foo and the subprocesses when in cui subsystem to create 
>>> visible consoles)
>>>
>>> (just to share it here)
>>>
>>
>> To recap our private conversation, there are nice things about that 
>> solution: it makes such invocation more similar to a more common 
>> situation on Windows and I like that aspect. My main concern is that 
>> it will make invoking Wine in situations when there is no Unix 
>> console available much more expensive, because we'd need to create an 
>> extra conhost process that would be useless in majority of cases. I 
>> know that we have some users using Wine as part of their Unix 
>> scripts, likely ran in the background, for whom it's likely to 
>> provide worse performance due to need to create twice as many Wine 
>> processes. It may not be a deal breaker, but I think it's a concern 
>> that we should consider.
>>
>>
>> One possible solution to that would be, for example, to have 
>> something like CONSOLE_HANDLE_SHELL_NO_WINDOW, which would be 
>> inherited by CreateProcess(0) and prevent from creating an actual new 
>> console. This would achieve most of this patch's goals with lower 
>> runtime price.
>>
>>
>> Other possible solution is more specific to Wine tests, which are 
>> causing most of those problems. We could just build tests as GUI 
>> applications and avoid the problem in the first place. It's not a 
>> general solution, through. We could maybe have wineconsole 
>> --no-window option that, instead of using AllocConsole, would use 
>> CREATE_NO_WINDOW. This would essentially give user an opt-in option 
>> to achieve the same outcome as your patch.
>>
>>
>> Anyway, none of above is perfect. I just thrown more ideas to the 
>> pool, hoping for your and/or other's opinions.
>>
>>
>> I think that the root of the problem is that there is no single right 
>> thing when Wine is invoked by Unix process with no Unix console 
>> available (when Unix console is available, the choice to use it is 
>> mostly uncontroversial). In some cases, creating a console window is 
>> desired, while for others it's not. Currently user is able to force 
>> console window creation by running explicitly wineconsole, but the 
>> opposite is not possible under assumption that "default" is good for 
>> other cases. This is an equivalent of creating the process with 
>> DETACHED_PROCESS on Windows.
>>
>
> anyway it would be interesting to have a tool (say wineconsole) where 
> we could launch a wine binary with a given console setup (=detached, 
> =window, =no-window...); optinonaly, it should also take care of 
> redirection of unix std handles (and pass them to subchild)... that 
> would require another flag (like --std-inherit). this would allow to 
> have an answer to any specific need
>
> I'm all against moving wine tests to GUI subsystem... it doesn't solve 
> the bottom line issue: windows "regular" behavior is that CUI 
> processes are attached to a console...
>
> yet to decide what's the best option
>
> - for Wine's default for initial process not connected to a unix tty
>
> - for testbot
>
> I'll wait for this to be settled before zero:ing ConsoleHandle for GUI 
> processes...
>
>
that patch might work instead

- at least, with it, testbot seems happier on user32:input 
(https://testbot.winehq.org/JobDetails.pl?Key=112035&f101=task.log#k101)

- applies on top of the two previous patches


in terms of performance, I measured locally:

4 different settings:

- when starting attached to a unix console

- when starting not attached to a unix console (current wine tree)

- when starting not attached to a unix console (current wine tree + 
ALLOC_NO_WINDOW for initial process)

- when starting not attached to a unix console (current wine tree + 
SHELL_NO_WINDOW for initial process = the attached patch)


three measures:

==============

in all measures, using time on running tasklist.exe (which only does a 
couple of FIXME:s; so a proxy for process startup time - and tear down)

done on bare metal, with a relatively idle machine with "decent" #procs 
and memory... so values to be seem as best case, heavier work load might 
increase the differences


measure #1:

starting a new wine session: start done 10 times (waiting in between for 
wineserver to shut down; with warm up to fill fs caches)

      |            | /w patch        | full session init |
      |------------+-----------------+-------------------|
      | Unix shell |                 | 166.3 ms          |
      | no shell   |                 | 163.7 ms          |
      | no shell   | alloc_no_window | 166 ms            |
      | no shell   | shell_no_window | 164 ms            |
roughly, a slight degradation when starting up conhost.exe ; no 
measurable difference when not attached to a unix console

measure #2:

keeping an active wine session, starting 1000 times tasklist in a row

       |            | /w patch        | incremental start |
       |------------+-----------------+-------------------|
       | Unix shell |                 | 9,440 ms          |
       | no shell   |                 | 7,903 ms          |
       | no shell   | alloc_no_window | 9,271 ms          |
       | no shell   | shell_no_window | 7,951 ms          |
so a 15 to 20% impact on process startup... shell_no_window doesn't show 
measurable difference from current situation for non attached processes

measure #3

same logic as measure #2, using start.exe in the middle

       |            | /w patch        | incremental start |
       |------------+-----------------+-------------------|
       | Unix shell |                 | 38.315 ms         |
       | no shell   |                 | 31.945 ms         |
       | no shell   | alloc_no_window | 38.472 ms         |
       | no shell   | shell_no_window | 32.428 ms         |
confirms reasults of measure #2, but with a huge impact of start.exe 
(path lookup...)


-------------- next part --------------
diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c
index 046eee6147c..1a8d1e822b8 100644
--- a/dlls/kernelbase/console.c
+++ b/dlls/kernelbase/console.c
@@ -2303,5 +2303,6 @@ void init_console( void )
         if (RtlImageNtHeader( mod )->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
             alloc_console( no_window );
     }
-    else if (params->ConsoleHandle) create_console_connection( params->ConsoleHandle );
+    else if (params->ConsoleHandle && params->ConsoleHandle != CONSOLE_HANDLE_SHELL_NO_WINDOW)
+        create_console_connection( params->ConsoleHandle );
 }
diff --git a/dlls/ntdll/unix/env.c b/dlls/ntdll/unix/env.c
index 64117e70abe..2ead6c1fcc3 100644
--- a/dlls/ntdll/unix/env.c
+++ b/dlls/ntdll/unix/env.c
@@ -1684,6 +1684,8 @@ static void get_initial_console( RTL_USER_PROCESS_PARAMETERS *params )
         params->hStdOutput = (HANDLE)((UINT_PTR)params->hStdOutput | 1);
         output_fd = 1;
     }
+    if (!params->ConsoleHandle && main_image_info.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI)
+        params->ConsoleHandle = CONSOLE_HANDLE_SHELL_NO_WINDOW;
 
     if (output_fd != -1)
     {
diff --git a/include/wine/condrv.h b/include/wine/condrv.h
index 452ce552da1..94afb1d49c4 100644
--- a/include/wine/condrv.h
+++ b/include/wine/condrv.h
@@ -191,5 +191,6 @@ struct condrv_ctrl_event
 #define CONSOLE_HANDLE_ALLOC            UlongToHandle(1)
 #define CONSOLE_HANDLE_ALLOC_NO_WINDOW  UlongToHandle(2)
 #define CONSOLE_HANDLE_SHELL            UlongToHandle(3)
+#define CONSOLE_HANDLE_SHELL_NO_WINDOW  UlongToHandle(5)
 
 #endif /* _INC_CONDRV */


More information about the wine-devel mailing list