Desktop Heap Overview

Desktop Heap Overview

Rate This

 

Desktop heap is probably not something that you spend a lot of time thinking about, which is a good thing.  However, from time to time you may run into an issue that is caused by desktop heap exhaustion, and then it helps to know about this resource.  Let me state up front that things have changed significantly in Vista around kernel address space, and much of what I’m talking about today does not apply to Vista.

 

Laying the groundwork: Session Space

To understand desktop heap, you first need to understand session space.  Windows 2000, Windows XP, and Windows Server 2003 have a limited, but configurable, area of memory in kernel mode known as session space.  A session represents a single user’s logon environment.  Every process belongs to a session.  On a Windows 2000 machine without Terminal Services installed, there is only a single session, and session space does not exist.  On Windows XP and Windows Server 2003, session space always exists.  The range of addresses known as session space is a virtual address range.  This address range is mapped to the pages assigned to the current session.  In this manner, all processes within a given session map session space to the same pages, but processes in another session map session space to a different set of pages. 

Session space is divided into four areas: session image space, session structure, session view space, and session paged pool.  Session image space loads a session-private copy of Win32k.sys modified data, a single global copy of win32k.sys code and unmodified data, and maps various other session drivers like video drivers, TS remote protocol driver, etc.  The session structure holds various memory management (MM) control structures including the session working set list (WSL) information for the session.  Session paged pool allows session specific paged pool allocations.  Windows XP uses regular paged pool, since the number of remote desktop connections is limited.  On the other hand, Windows Server 2003 makes allocations from session paged pool instead of regular paged pool if Terminal Services (application server mode) is installed.  Session view space contains mapped views for the session, including desktop heap. 

Session Space layout:

Session Image Space: win32k.sys, session drivers

Session Structure: MM structures and session WSL

Session View Space: session mapped views, including desktop heap

Session Paged Pool

 

Sessions, Window Stations, and Desktops

You’ve probably already guessed that desktop heap has something to do with desktops.  Let’s take a minute to discuss desktops and how they relate to sessions and window stations.  All Win32 processes require a desktop object under which to run.  A desktop has a logical display surface and contains windows, menus, and hooks.  Every desktop belongs to a window station.  A window station is an object that contains a clipboard, a set of global atoms and a group of desktop objects.  Only one window station per session is permitted to interact with the user. This window station is named "Winsta0."  Every window station belongs to a session.  Session 0 is the session where services run and typically represents the console (pre-Vista).  Any other sessions (Session 1, Session 2, etc) are typically remote desktops / terminal server sessions, or sessions attached to the console via Fast User Switching.  So to summarize, sessions contain one or more window stations, and window stations contain one or more desktops.

You can picture the relationship described above as a tree.  Below is an example of this desktop tree on a typical system:

- Session 0

|   |

|   ---- WinSta0           (interactive window station)

|   |      |

|   |      ---- Default    (desktop)

|   |      |

|   |      ---- Disconnect (desktop)

|   |      |

|   |      ---- Winlogon   (desktop)

|   |

|   ---- Service-0x0-3e7$  (non-interactive window station)

|   |      |

|   |      ---- Default    (desktop)

|   |

|   ---- Service-0x0-3e4$  (non-interactive window station)

|   |      |

|   |      ---- Default    (desktop)

|   |

|   ---- SAWinSta          (non-interactive window station)

|   |      |

|   |      ---- SADesktop  (desktop)

|   |

- Session 1

|   |

|   ---- WinSta0           (interactive window station)

|   |      |

|   |      ---- Default    (desktop)

|   |      |

|   |      ---- Disconnect (desktop)

|   |      |

|   |      ---- Winlogon   (desktop)

|   |

- Session 2

    |

    ---- WinSta0           (interactive window station)

           |

           ---- Default    (desktop)

           |

           ---- Disconnect (desktop)

           |

           ---- Winlogon   (desktop)

 

In the above tree, the full path to the SADesktop (as an example) can be represented as “Session 0\SAWinSta\SADesktop”.

 

Desktop Heap – what is it, what is it used for?

Every desktop object has a single desktop heap associated with it.  The desktop heap stores certain user interface objects, such as windows, menus, and hooks.  When an application requires a user interface object, functions within user32.dll are called to allocate those objects.  If an application does not depend on user32.dll, it does not consume desktop heap.  Let’s walk through a simple example of how an application can use desktop heap. 

1.     An application needs to create a window, so it calls CreateWindowEx in user32.dll.

2.     User32.dll makes a system call into kernel mode and ends up in win32k.sys.

3.     Win32k.sys allocates the window object from desktop heap

4.     A handle to the window (an HWND) is returned to caller

5.     The application and other processes in the same session can refer to the window object by its HWND value

 

Where things go wrong

Normally this “just works”, and neither the user nor the application developer need to worry about desktop heap usage.  However, there are two primary scenarios in which failures related to desktop heap can occur:

  1. Session view space for a given session can become fully utilized, so it is impossible for a new desktop heap to be created.
  2. An existing desktop heap allocation can become fully utilized, so it is impossible for threads that use that desktop to use more desktop heap.

 

So how do you know if you are running into these problems?  Processes failing to start with a STATUS_DLL_INIT_FAILED (0xC0000142) error in user32.dll is a common symptom.  Since user32.dll needs desktop heap to function, failure to initialize user32.dll upon process startup can be an indication of desktop heap exhaustion.  Another symptom you may observe is a failure to create new windows.  Depending on the application, any such failure may be handled in different ways.  Note that if you are experiencing problem number one above, the symptoms would usually only exist in one session.  If you are seeing problem two, then the symptoms would be limited to processes that use the particular desktop heap that is exhausted.

 

Diagnosing the problem

So how can you know for sure that desktop heap exhaustion is your problem?  This can be approached in a variety of ways, but I’m going to discuss the simplest method for now.  Dheapmon is a command line tool that will dump out the desktop heap usage for all the desktops in a given session.  See our first blog post for a list of tool download locations.  Once you have dheapmon installed, be sure to run it from the session where you think you are running out of desktop heap.  For instance, if you have problems with services failing to start, then you’ll need to run dheapmon from session 0, not a terminal server session.

Dheapmon output looks something like this:

Desktop Heap Information Monitor Tool (Version 7.0.2727.0)

Copyright (c) 2003-2004 Microsoft Corp.

-------------------------------------------------------------

  Session ID:    0 Total Desktop: (  5824 KB -    8 desktops)

 

  WinStation\Desktop            Heap Size(KB)    Used Rate(%)

-------------------------------------------------------------

  WinSta0\Default                    3072              5.7

  WinSta0\Disconnect                   64              4.0

  WinSta0\Winlogon                    128              8.7

  Service-0x0-3e7$\Default            512             15.1

  Service-0x0-3e4$\Default            512              5.1

  Service-0x0-3e5$\Default            512              1.1

  SAWinSta\SADesktop                  512              0.4

  __X78B95_89_IW\__A8D9S1_42_ID       512              0.4

-------------------------------------------------------------

 

As you can see in the example above, each desktop heap size is specified, as is the percentage of usage.  If any one of the desktop heaps becomes too full, allocations within that desktop will fail.  If the cumulative heap size of all the desktops approaches the total size of session view space, then new desktops cannot be created within that session.  Both of the failure scenarios described above depend on two factors: the total size of session view space, and the size of each desktop heap allocation.  Both of these sizes are configurable. 

 

Configuring the size of Session View Space

Session view space size is configurable using the SessionViewSize registry value.  This is a REG_DWORD and the size is specified in megabytes.  Note that the values listed below are specific to 32-bit x86 systems not booted with /3GB.  A reboot is required for this change to take effect.  The value should be specified under:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management

OS

Size if no registry value configured

Default registry value

Windows 2000 *

20 MB

none

Windows XP

20 MB

48 MB

Windows Server 2003

20 MB

48 MB

* Settings for Windows 2000 are with Terminal Services enabled and hotfix 318942 installed.  Without the Terminal Services installed, session space does not exist, and desktop heap allocations are made from a fixed 48 MB region for system mapped views.  Without hotfix 318942 installed, the size of session view space is fixed at 20 MB.

The sum of the sizes of session view space and session paged pool has a theoretical maximum of slightly under 500 MB for 32-bit operating systems.  The maximum varies based on RAM and various other registry values.  In practice the maximum value is around 450 MB for most configurations.  When the above values are increased, it will result in the virtual address space reduction of any combination of nonpaged pool, system PTEs, system cache, or paged pool.

 

Configuring the size of individual desktop heaps

Configuring the size of the individual desktop heaps is bit more complex.  Speaking in terms of desktop heap size, there are three possibilities:

·         The desktop belongs to an interactive window station and is a “Disconnect” or “Winlogon” desktop, so its heap size is fixed at 64KB or 128 KB, respectively (for 32-bit x86)

·         The desktop heap belongs to an interactive window station, and is not one of the above desktops.  This desktop’s heap size is configurable.

·         The desktop heap belongs to a non-interactive window station.  This desktop’s heap size is also configurable.

 

The size of each desktop heap allocation is controlled by the following registry value:

            HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems\Windows

 

 The default data for this registry value will look something like the following (all on one line):

               %SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows

               SharedSection=1024,3072,512 Windows=On SubSystemType=Windows

               ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3

               ServerDll=winsrv:ConServerDllInitialization,2 ProfileControl=Off

               MaxRequestThreads=16

                                                           

 

The numeric values following "SharedSection=" control how desktop heap is allocated. These SharedSection values are specified in kilobytes.

The first SharedSection value (1024) is the shared heap size common to all desktops. This memory is not a desktop heap allocation, and the value should not be modified to address desktop heap problems.

The second SharedSection value (3072) is the size of the desktop heap for each desktop that is associated with an interactive window station, with the exception of the “Disconnect” and “Winlogon” desktops.

The third SharedSection value (512) is the size of the desktop heap for each desktop that is associated with a "non-interactive" window station. If this value is not present, the size of the desktop heap for non-interactive window stations will be same as the size specified for interactive window stations (the second SharedSection value). 

Consider the two desktop heap exhaustion scenarios described above.  If the first scenario is encountered (session view space is exhausted), and most of the desktop heaps are non-interactive, then the third SharedSection can be decreased in an effort to allow more (smaller) non-interactive desktop heaps to be created.  Of course, this may not be an option if the processes using the non-interactive heaps require a full 512 KB.  If the second scenario is encountered (a single desktop heap allocation is full), then the second or third SharedSection value can be increased to allow each desktop heap to be larger than 3072 or 512 KB.  A potential problem with this is that fewer total desktop heaps can be created.

 

What are all these window stations and desktops in Session 0 anyway?

Now that we know how to tweak the sizes of session view space and the various desktops, it is worth talking about why you have so many window stations and desktops, particularly in session 0.  First off, you’ll find that every WinSta0 (interactive window station) has at least 3 desktops, and each of these desktops uses various amounts of desktop heap.  I’ve alluded to this previously, but to recap, the three desktops for each interactive window stations are:

·         Default desktop - desktop heap size is configurable as described below

·         Disconnect desktop - desktop heap size is 64k on 32-bit systems

·         Winlogon desktop - desktop heap size is 128k on 32-bit systems

 

Note that there can potentially be more desktops in WinSta0 as well, since any process can call CreateDesktop and create new desktops.

Let’s move on to the desktops associated with non-interactive window stations: these are usually related to a service.  The system creates a window station in which service processes that run under the LocalSystem account are started. This window station is named service-0x0-3e7$. It is named for the LUID for the LocalSystem account, and contains a single desktop that is named Default. However, service processes that run as LocalSystem interactive start in Winsta0 so that they can interact with the user in Session 0 (but still run in the LocalSystem context).

Any service process that starts under an explicit user or service account has a window station and desktop created for it by service control manager, unless a window station for its LUID already exists. These window stations are non-interactive window stations.  The window station name is based on the LUID, which is unique for every logon.  If an entity (other than System) logs on multiple times, a new window station is created for each logon.  An example window station name is “service-0x0-22e1$”.

A common desktop heap issue occurs on systems that have a very large number of services.  This can be a large number of unique services, or one (poorly designed, IMHO) service that installs itself multiple times.  If the services all run under the LocalSystem account, then the desktop heap for Session 0\Service-0x0-3e7$\Default may become exhausted.  If the services all run under another user account which logs on multiples times, each time acquiring a new LUID, there will be a new desktop heap created for every instance of the service, and session view space will eventually become exhausted.

Given what you now know about how service processes use window stations and desktops, you can use this knowledge to avoid desktop heap issues.  For instance, if you are running out of desktop heap for the Session 0\Service-0x0-3e7$\Default desktop, you may be able to move some of the services to a new window station and desktop by changing the user account that the service runs under.

 

Wrapping up

I hope you found this post interesting and useful for solving those desktop heap issues!  If you have questions are comments, please let us know.

 

- Matthew Justice

 

[Update: 7/5/2007 - Desktop Heap, part 2 has been posted]

[Update: 9/13/2007 - Talkback video: Desktop Heap has been posted]

[Update: 3/20/2008 - The default interactive desktop heap size has been increased on 32-bit Vista SP1]

 

Leave a Comment
  • Please add 3 and 8 and type the answer here:
  • Post
  • Why a process, that creates a desktop in its session using CreateDektopEx(), cannot specify (or tweak) the Desktop Heap size it really needs?

    Isn't there some envisioned improvement (notably for most services that don't need any service from the desktop), so that the default non-interative dektop heaps would be reduced by default, and increased only on demand by the specific services that need it?

    Note that the session manager could look at the prefered desktop heap size within a registry entry associated to the service that performs the CreateDektopEx() call, even if the code of this service is not modified. This would change very simply the effective default desktop heap size used by those non-interactive services, and it would still allow specific installations of Windows to be tuned by just adding or changing such registry entry for the service (whose absence would mean that the third parameter, specified in the registry for the settings of the session manager, would be used as it is today).

    Finally, changing at run-time the desktop heap size should be possible by performing an IoControl request to the handle associated to the desktop; this would not necessarily require a new API, just a new IoControl request type, which may remain specific to the current version of Windows, and that should be secured using the user priviledges associated to the calling process, according to the user account owning the session object).

    An optional helper API could be created on top of this IoControl, using a new modelized and standardized API similar to ToolHelp;

    it could also be done by extending it to cover the administration of desktop heaps, including the possibility to include them in the list of other Ressource Monitor collectors, at least in read-only mode, so that desktop heap resource exhaustion can be more easily diagnosed; here also, no additional API is required in Windows, and we could use the standard "Performance Analysis tool" (in the existing collection of Administrative tools) to query the current status of Desktop Heap and Session objects: just assign them with a Performance object name.

    Such Performance helper DLL should also be made available to Windows XP (based on your existing advanced debugging tool described above) even if it does not allow an application to control the Desktop Heap sizes or the Session pool size at run time.

  • Now that Vista features the LUA isolation mechanism that creates additional sesion objects and isolates the interactive services from other interactive user applications, it should be good to describe how the various sessions and desktops are shared, isolated, or tweakable in Vista.

    And isn't there an additional desktop used by the LUA alerts that are displayed on top of the current desktop with a transparent greyed effect, when LUA is enabled in Vista's session manager?

    [UAC uses the per-session winlogon desktop (also known as the secure desktop) to display prompts. The “transparent greyed effect” is basically a bitmap of what the user’s desktop looked like at the time of the prompt. - Matthew]
  • This sounds suspiciously like it might be the cause of a problem I'm having with some Win2003 webservers. They run a lot of asp code under several application pools. Sometimes the ASP code fails simply saying "out of memory" and the only way to get it working again is to recycle the pool. Any advice?

    [This is probably not a desktop heap issue. You can run dheapmon and check desktop heap usage at the time of the problem to check. - Matthew]
  • I can't thank you enough for posting this information.  This article helped me suggest a workaround for a serious customer problem that I never would have figured out otherwise.

    Our application runs as a Service, and its purpose is to start a number of other (non-service) processes (maybe 30 or 40) that make up our system.  It works fine, except on Windows XP SP2 systems, where, after successfully starting 20-25 processes, any additional processes it creates die immediately with the 0xC0000142 error.  I could never figure out why until I read this article.  By changing "SharedSection=1024,3072,512" to be "1024,3072,256", the behavior changed so that I could only run 8 processes at once.  Changing the 512 to be 1024 allows the application to start at least 40 processes without any problem.  So, I know I am on the right track.

    However, I still have a couple of questions.  None of the processes that are started by this service interact with the desktop at all.  So, I am wondering if I can change the way our service creates these processes such that they are not affected by the Desktop Heap limitations at all.  The service itself gets created with the SERVICE_WIN32_OWN_PROCESS flag, and then it calls CreateProcess for each process.  I have played with the CREATE_NEW_PROCESS_GROUP and DETACHED_PROCESS flags, and found that using the DETACHED_PROCESS flag allows the service to create about 7 or 8 more processes then without it, but still limited.  Also, if I run my service process interactively, it ALWAYS starts ALL the processes without any problem.

    Is there any way for a service to create backgound processes that are not subject to the Desktop Heap limitation?

    [All process that load user32.dll use desktop heap, and all such processes are subject to desktop heap size limits. In your case, it sounds like your service is starting multiple processes that share a non-interactive desktop. These processes will also share a desktop heap. By running your service interactively, your service will use the 3072 KB interactive desktop heap instead of a 512 KB non-interactive heap. If you want to run the service non-interactively, then it sounds like increasing the 3rd SharedSection was a good choice. The only way to prevent desktop heap from being used at all is to not load user32.dll at all (which is often not an option). - Matthew]
  • Hi,

     Great article, I was struggling to find any info on this!

    I have a Windows Server 2K3 running Exchange 2003. I occasionally get the system event log error "Failed to create a desktop due to desktop heap exhaustion"

    I originally changed the settings detailed here - http://www.jsifaq.com/SF/Tips/Tip.aspx?id=8057

    This has not fixed the problem, at present my SharedSection settings are default, would I want to change the second or third setting, what would be recommended.

    Many Thanks

    Andy

    [“Failed to create a desktop due to desktop heap exhaustion.” is logged when the heap itself cannot be created. If a desktop heap cannot be created, then the entire desktop creation attempt fails. Usually a failure to create a new desktop heap means that session view space is exhausted for the session. You may be able to resolve this issue by increasing the size of session view space (using the SessionViewSize registry value) or by decreasing the third shared section value (assuming session view space is primarily used by non-interactive desktop heaps), to allow for more heaps to be created. Before making any changes, I suggest you use dheapmon to view desktop heap usage on your system shortly after you see the error. It helps to understand the usage of desktop heap before making changes. FYI, the desktop heap failure errors are only logged once per session to avoid a flood of events in the event log. So you may actually have more than one failure per session, but only one is logged. Desktop heap logging can be enabled or disabled with the DesktopHeapLogging registry value (see KB 810807). - Matthew]
  • How would I determine if the box has hotfix 318942 installed?

    [318942 contained a kernel binary (ntoskrnl.exe, ntkrnlmp.exe, etc) with a version of 5.0.2195.6797. Make sure that the kernel you are running is 5.0.2195.6797 or later. - Matthew]
  • Hello,

    This is a great article - thank you. I know now how to change the heap size manually in the Registry. Now I would like to detect programmatically if there is not enough heap space when my program starts. Are there any Windows API calls to do this?

    Thank you.

    [The size and usage of the desktop heaps are not obtainable using Windows API functions. Desktop heaps are a resource that only USER accesses directly (via its kernel mode implementation in win32k.sys), and would usually be considered an internal implementation detail of USER. Consequently, Win32 doesn’t expose many functions for directly dealing with desktop heap. Beginning with Vista, there a couple of exceptions: GetUserObjectInformation and be used with UOI_HEAPSIZE to get the heap size (but not the usage), and CreateDesktopEx can be used to specify a new heap size. - Matthew]
  • Does LUID "Service-0x0-3e7$\Default" represent all the services that run as LocalSystem?  If not, is there a way to map that back to a specific Windows service?

    Thanks

    [Yes, the service processes that run under local system will run under the Service-0x0-3e7$ window station. By default, the “Default” desktop will be used by threads in this process, but other desktops could be created and used. - Matthew]
  • Matthew - great article, many thanks!

    We have a Windows 2003 Terminal Server SP2, with 4GB Physical RAM and using the following boot.ini switches:

    /noexecute=optout /fastdetect /3GB /PAE /USERVA:3030

    The server hosts about 10-15 terminal clients. There is a CRM client (Amtangee) installed which queries a separate Amtangee SQL Server.

    Users complain that if they open several faxes at the same time within Amtangee, they get a warning error along the lines of "...not enough memory storage is available to process this command". The client then crashes. Only after a logout/login does the client app work again, until several faxes are opened...

    We spoke with Amtangee and they believe it's to do with GDI-Handles. We have experimented with different settings but still have the same problem. Registry keys changed are:

    GDIProcessHandleQuota 65536

    UserProcessHandleQuota 65536

    LargeSystemCache 1

    DisablePagingExecuive 1

    PagedPoolSize 0

    NonPagedPoolSize 0

    SharedSection 1024,4096,512

    I have read your article with interest. What I would appreciate are you thoughts of what switches are best to use for boot.ini along with memory management, sessions & desktop heaps and any other optimisation tips for our terminal server.

    I really look forward to your comments. Many thanks, Oliver

    [Troubleshooting at this complexity and making specific configuration recommendations is beyond the scope of this blog, but I’d be glad to give some thoughts. It sounds like Amtangee is throwing ERROR_NOT_ENOUGH_MEMORY which is “Not enough storage is available to process this command.” This is fairly generic error, and it may be that a Windows function is returning it to Amtangee, and they are in turn displaying it to the user. Or it may be that Amtangee hit a failure within their code, and this is just the error they chose to return. In either case, it would be worth investigating if Amtangee can tell you if exactly what condition led to the return of this error. That would be a good starting point to determine what resource may be exhausted. Since Amtangee has already referenced GDI handles a possible problem, I suggest you pull up task manager while in state and see what the GDI Object count is for each process in the session. See if any process has an excessive GDI count, or if the total GDI handle count for the session is excessive. If the problem only affects one session at a time, then the resource is not going to be a system wide resource like page pool. You could be running out of session view space or session paged pool. You could also verify desktop heap usage using dheapmon. - Matthew]
  • Hello,

    Great article! But I don't know if desktop heap is what I'm facing. I have a problem with some applications running or my computer. When I launch some applications they come up with blank(white) screens. An example is starting up Windows Help & Support, the right window is always blank regardless of what I click. Same goes for my MS Project, I get a plain white page. Most applications give me a plain white page or just an empty page.

    I'm really not sure what the problem is. What do you think? I would appreciate some help here.

    Thank you.

    [I would suggest you start by using dheapmon to see if you are indeed exhausting desktop heap. - Matthew]
  • We're facing precisely this problem. But I don't know where to go from here. Telling users to raise SharedSection and reboot just isn't the solution. We need to figure out where we're allocating these desktop objects. dheapmon seems to give the bottom-line numbers but no detail.

    How can I find out what objects are being allocated in the desktop heap? And preferably which dll is actually causing them to be allocated?

    Is there some convenient function I can set a breakpoint on and catch each time user32.dll actually allocates memory from it? Then I could look at the backtrace and see what's going on. Or some magic options to dheapmon to get more useful detail? Or something equivalent to ltrace/strace/ktrace which will let me see what what's going on?

     

    [Assuming an individual desktop heap is exhausted (as opposed to an exhausted SessionViewSpace),  I recommend you start by looking at the USER object count in task manager. That will at least tell you what process is the likely primary consumer of desktop heap. If you stop the process in question, you should see desktop heap usage drop in dheapmon.  (You may have already narrowed things down this far, but I’m covering my bases here).  Once you know what process is using the heap, you’ll need to determine what kind of USER objects are being allocated by the process.  Not all USER objects come out of desktop heap, but windows, menus, and hooks do.   In most cases, it is window objects that are consuming the heap, as they are commonly used.  Setting a breakpoint on USER32!NtUserCreateWindowEx will allow you to catch the process creating windows, and see if anything looks out of the ordinary (this breakpoint may be hit often).  You could also use SPY++ to look for an excessive number of hidden windows that you wouldn’t be able to observe without SPY++ or the debugger.   - Matthew]
  • Paulette, when even Task Manager comes up empty, I know it is time to reboot.

    Another symptom is pulldown menus with missing items.  Sometimes a pulldown would show the separators, but none of the real items.

    I have had this since NT days, when I had trouble keeping NT up for more than a couple of days.  Now, with 2000 and XP, it is more like a week.  I do keep dozens of windows open.  For example, I am quick to open Outlook emails, but slow to close them.

    One thing that often pushes Windows over the breaking point -- opening any of the Office apps.  It is as if they slam the Heap (or whatever) more than most apps.

  • Thanks a lot, Matthew. I guess I didn't give enough context though. This is our own software I'm talking about. I can see clearly that each spawned process was taking up just over 9k of Desktop space which out of 512kb goes quickly. This is a non-interactive server daemon so it isn't creating any windows and really doesn't have any business using any Desktop Heap allocations. On unix we handle thousands of processes just fine so ideally we would want to consume 0 Desktop Heap on windows since we really don't need it and want to scale just as well.

    The problem isn't that our code is creating windows or any other GUI elements. The problem is that some DLLs we load are allocating space from the Desktop Heap when they're initialized.

    We've already tracked down 6k of the 9k by removing calls to wsprintf and SHGetFolderPath. I can't imagine why either of these should need 6k of space per process in a shared memory segment but presumably they come from DLLs that are initializing some unrelated data structures for future use. We've replaced them with our own snprintf and using the APPDATA environment variable.

    Now the problem is that we're still allocating 3k of Desktop Heap and that's still limiting how many processes we can spawn. I'll try a breakpoint on CreateWindowEx like you suggest but I suspect it's not hidden windows but something more obscure. Surely all the clients of the Destop Heap including CreateWindowEx call some common memory management function to actually allocate space from it? If I could set a breakpoint there that would be ideal.

    [Thanks for the clarification. Let me give a little background on how desktop heap allocations are made. The desktop heaps are in kernel mode virtual address space, so individual desktop heap allocations have to be made by a component running in kernel mode. In particular, win32k.sys is the only kernel mode component that makes desktop heap allocations. win32k.sys in the kernel mode side of Win32, and it includes both the window manager (USER) and GDI. It is the window manager piece of win32k.sys that uses desktop heap. The functionality of the window manager is exposed to processes running in user mode through user32.dll. It is user32.dll that exports user mode callable functions that are implemented in win32k.sys. So if a process does not load user32.dll, it will not use desktop heap.

    Regarding your question about setting a breakpoint that will catch desktop heap allocations... yes, there is such a function - win32k!DesktopAlloc. However, this is a kernel mode function, and to set a breakpoint on it will require that you use a kernel debugger.

    Since your process is non-interactive and you do not create windows directly, it is worth considering what components your code relies on that may be creating windows on your behalf. If you app uses COM then these allocations could be from OLE STA thread windows. If you are building your app as a console subsystem application you may want to consider building it as a windows subsystem app instead to avoid the auto creation of the console window. No windows are created automatically for windows subsystem apps. - Matthew]
  • Just had a server totally stall after doing a reboot to apply the latest patches.

    During the first restart got the event id 244

    "Failed to create a desktop due to desktop heap exhaustion." About four hours after this, the server just stopped responding. Did a reset and it came up OK with no errors, but nothing else in the log.

    My questions are:

    Could a problem with the desktop heap cause the server to stop responding (not even to ping!)?

    What could have caused this problem in the first place.

    [Desktop heap allocation failures alone won’t lead to a complete server hang. The underlying reason for the hang is hard to guess based on the limited information we have. If you see this problem continue to happen you could force a memory dump of the system when it hangs (see KB 244139) and work with Microsoft support to have the dump analyzed.]
  • A very informative article, thank you. Can you tell me what are the "allowed" values for the non-interactive desktop heap? We are having problems with 1024 (failure to create a new process at a certain point in one of our applications), but 2048 is too much (some services don't start). Is it OK to use a number in between these values, or must it be a power of 2?

    [You can use a size that is between 1024 and 2048. The value that specify will be internally rounded up to a multiple of the page size (4KB on x86).]
Page 4 of 7 (100 items) «23456»