* 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

@@ -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)