* ntdll.h (struct _PEB): Add EnvironmentUpdateCount member.

* spawn.cc (child_info_spawn::worker): Speed up job recognition.  Expand
	comment to explain every little detail and so we never forget.
	* wincap.h (wincaps::has_program_compatibility_assitant): New element.
	* wincap.cc: Implement above element throughout.
This commit is contained in:
Corinna Vinschen 2012-02-17 14:26:18 +00:00
parent e86c278998
commit 1cb1472404
5 changed files with 66 additions and 20 deletions

View File

@ -1,3 +1,11 @@
2012-02-17 Corinna Vinschen <corinna@vinschen.de>
* ntdll.h (struct _PEB): Add EnvironmentUpdateCount member.
* spawn.cc (child_info_spawn::worker): Speed up job recognition. Expand
comment to explain every little detail and so we never forget.
* wincap.h (wincaps::has_program_compatibility_assitant): New element.
* wincap.cc: Implement above element throughout.
2012-02-17 Corinna Vinschen <corinna@vinschen.de>
* mount.cc (get_disk_type): Drop unneeded toupper call. Convert case

View File

@ -1,7 +1,7 @@
/* ntdll.h. Contains ntdll specific stuff not defined elsewhere.
Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011 Red Hat, Inc.
2009, 2010, 2011, 2012 Red Hat, Inc.
This file is part of Cygwin.
@ -689,7 +689,9 @@ typedef struct _PEB
BYTE Reserved3[4];
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
BYTE Reserved4[436];
BYTE Reserved4[8];
ULONG EnvironmentUpdateCount;
BYTE Reserved5[424];
ULONG SessionId;
} PEB, *PPEB;

View File

@ -455,23 +455,49 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
c_flags |= CREATE_SEPARATE_WOW_VDM | CREATE_UNICODE_ENVIRONMENT;
/* We're adding the CREATE_BREAKAWAY_FROM_JOB flag here to workaround issues
with the "Program Compatibility Assistant (PCA) Service" observed on
Windows 7. For some reason, when starting long running sessions from
mintty, the affected svchost.exe process takes more and more memory and
at one point takes over the CPU. At this point the machine becomes
unresponsive. The only way to get back to normal is to stop the entire
mintty session, or to stop the PCA service. However, a process which
is controlled by PCA is part of a compatibility job, which allows child
processes to break away from the job. This helps to avoid this issue. */
JOBOBJECT_BASIC_LIMIT_INFORMATION jobinfo;
if (QueryInformationJobObject (NULL, JobObjectBasicLimitInformation,
&jobinfo, sizeof jobinfo, NULL)
&& (jobinfo.LimitFlags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK
| JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
if (wincap.has_program_compatibility_assitant ())
{
debug_printf ("Add CREATE_BREAKAWAY_FROM_JOB");
c_flags |= CREATE_BREAKAWAY_FROM_JOB;
/* We're adding the CREATE_BREAKAWAY_FROM_JOB flag here to workaround
issues with the "Program Compatibility Assistant (PCA) Service"
starting with Windows Vista. For some reason, when starting long
running sessions from mintty(*), the affected svchost.exe process
takes more and more memory and at one point takes over the CPU. At
this point the machine becomes unresponsive. The only way to get
back to normal is to stop the entire mintty session, or to stop the
PCA service. However, a process which is controlled by PCA is part
of a compatibility job, which allows child processes to break away
from the job. This helps to avoid this issue.
(*) Note that this is not mintty's fault. It has just been observed
with mintty in the first place. See the archives for more info:
http://cygwin.com/ml/cygwin-developers/2012-02/msg00018.html */
JOBOBJECT_BASIC_LIMIT_INFORMATION jobinfo;
/* Calling QueryInformationJobObject costs time. Starting with
Windows XP there's a function IsProcessInJob, which fetches the
information whether or not we're part of a job 20 times faster than
the call to QueryInformationJobObject. But we're still
supporting Windows 2000, so we can't just link to that function.
On the other hand, loading the function pointer at runtime is a
time comsuming operation, too. So, what we do here is to emulate
the IsProcessInJob function when called for the own process and with
a NULL job handle. In this case it just returns the value of the
lowest bit from PEB->EnvironmentUpdateCount (observed with WinDbg).
The name of this PEB member is the same in all (inofficial)
documentations of the PEB. Apparently it's a bit misleading.
As a result, we only call QueryInformationJobObject if we're on
Vista or later *and* if the PEB indicates we're running in a job.
Tested on Vista/32, Vista/64, W7/32, W7/64, W8/64. */
if ((NtCurrentTeb ()->Peb->EnvironmentUpdateCount & 1) != 0
&& QueryInformationJobObject (NULL, JobObjectBasicLimitInformation,
&jobinfo, sizeof jobinfo, NULL)
&& (jobinfo.LimitFlags & (JOB_OBJECT_LIMIT_BREAKAWAY_OK
| JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK)))
{
debug_printf ("Add CREATE_BREAKAWAY_FROM_JOB");
c_flags |= CREATE_BREAKAWAY_FROM_JOB;
}
}
if (mode == _P_DETACH)

View File

@ -2,7 +2,7 @@
capability class to the appropriate values.
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011 Red Hat, Inc.
2009, 2010, 2011, 2012 Red Hat, Inc.
This file is part of Cygwin.
@ -53,6 +53,7 @@ wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_stack_size_param_is_a_reservation:false,
has_console_logon_sid:false,
wow64_has_secondary_stack:false,
has_program_compatibility_assitant:false,
};
wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -85,6 +86,7 @@ wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) =
has_stack_size_param_is_a_reservation:false,
has_console_logon_sid:false,
wow64_has_secondary_stack:false,
has_program_compatibility_assitant:false,
};
wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -117,6 +119,7 @@ wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
has_stack_size_param_is_a_reservation:true,
has_console_logon_sid:false,
wow64_has_secondary_stack:false,
has_program_compatibility_assitant:false,
};
wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -149,6 +152,7 @@ wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_stack_size_param_is_a_reservation:true,
has_console_logon_sid:false,
wow64_has_secondary_stack:false,
has_program_compatibility_assitant:false,
};
wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -181,6 +185,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_stack_size_param_is_a_reservation:true,
has_console_logon_sid:false,
wow64_has_secondary_stack:false,
has_program_compatibility_assitant:false,
};
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -213,6 +218,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_stack_size_param_is_a_reservation:true,
has_console_logon_sid:false,
wow64_has_secondary_stack:true,
has_program_compatibility_assitant:false,
};
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -245,6 +251,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
has_stack_size_param_is_a_reservation:true,
has_console_logon_sid:false,
wow64_has_secondary_stack:false,
has_program_compatibility_assitant:true,
};
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
@ -277,6 +284,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
has_stack_size_param_is_a_reservation:true,
has_console_logon_sid:true,
wow64_has_secondary_stack:false,
has_program_compatibility_assitant:true,
};
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));

View File

@ -1,7 +1,7 @@
/* wincap.h: Header for OS capability class.
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011 Red Hat, Inc.
2009, 2010, 2011, 2012 Red Hat, Inc.
This file is part of Cygwin.
@ -43,6 +43,7 @@ struct wincaps
unsigned has_stack_size_param_is_a_reservation : 1;
unsigned has_console_logon_sid : 1;
unsigned wow64_has_secondary_stack : 1;
unsigned has_program_compatibility_assitant : 1;
};
class wincapc
@ -94,6 +95,7 @@ public:
bool IMPLEMENT (has_stack_size_param_is_a_reservation)
bool IMPLEMENT (has_console_logon_sid)
bool IMPLEMENT (wow64_has_secondary_stack)
bool IMPLEMENT (has_program_compatibility_assitant)
#undef IMPLEMENT
};